https://vjudge.net/problem/POJ-1639

题意:

有一群人,他们要去某一个地方,每个车可以装无数个人,给出了n条路,包含的信息有路连接的地方,以及路的长度,路是双向的,但是终点只有一个,并且终点能停的车的数量是有限制的,问最少走的路是多少。

思路:

因为终点的停车的数量是有限制的,所以终点的度是有限制的,又因为这题可以用最小生成树解决,所以就是度限制最小生成树。

度限制最小生成树求解思想并不复杂,首先我们把有度限制的点给忽略,然后给每一个连通分量求最小生成树,最后把每一个连通分量中与有度限制的点的距离最小的点与度限制点连接,假设有m个连通分量。

那么我们现在求出了m限制的最小生成树,假如限制数k < m,那么就无解。

当k >= m时,我们可以在m度限制mst的基础上,求m + 1,m + 2。。。k度限制最小生成树,求法也不是很难懂,但是程序就很难写了Orz。

如何求呢?枚举每一条未在生成树中与(现在我们把度限制点叫做R点)R点相连的边,然后把边加入生成树,必然会形成环,然后把环中与R点不相连的权值最大的边去掉,枚举之后的最小值就是m+1度限制最小生成树的值。然后依次求到k限制mst,求其中的最小值。

但是,依次枚举的话时间复杂度非常高,所以我们要优化。这时就用到了动态规划的思想。将与R点到其它点的边权值最大求出,之后加边的时候,直接替换就可以了。

转移方程 dp[v] = max(dp[father(v)],w(v , father(v)));

看不懂就多看几遍Orrrrrrrrrrrrrrrrrrrrrrrrz。

代码:

 #include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <map>
#include <string>
using namespace std; const int inf = 0x3f3f3f3f; struct edge
{
int x,y;
int v;
} a[],dp[]; map<string,int> mmp;
bool flag[][];
int par[];
int g[][]; int ans;
int num;
int du,lim; int fin(int x)
{
if (x == par[x]) return x;
else return par[x] = fin(par[x]);
} void unit(int x,int y)
{
x = fin(x);
y = fin(y); if (x == y) return; par[x] = y;
} void dfs(int cur,int pre)
{
for (int i = ;i <= num;i++)
{
if (i != pre && flag[cur][i])
{
if (dp[i].v == -)
{
if (dp[cur].v > g[cur][i])
{
dp[i] = dp[cur];
}
else
{
dp[i].x = cur;
dp[i].y = i;
dp[i].v = g[cur][i];
}
} dfs(i,cur);
}
}
} void solve(void)
{
for (int i = du + ;i <= lim;i++)
{
memset(dp,-,sizeof(dp)); dp[].v = -inf; for (int j = ;j <= num;j++)
if (flag[j][]) dp[j].v = -inf; dfs(,-); int mi = inf,tmp; for (int j = ;j <= num;j++)
{
if (g[][j] != -)
{
if (mi > g[][j] - dp[j].v)
{
mi = g[][j] - dp[j].v;
tmp = j;
}
}
} if (mi >= ) break; ans += mi; int x = dp[tmp].x,y = dp[tmp].y; flag[x][y] = flag[y][x] = ; flag[][tmp] = flag[tmp][] = ;
}
} int get_num(string aa)
{
if (mmp[aa]) return mmp[aa];
else
{
mmp[aa] = ++num;
return num;
}
} bool cmp(edge aa,edge bb)
{
return aa.v < bb.v;
} int main()
{
num = ; mmp["Park"] = ; memset(g,-,sizeof(g)); int n; scanf("%d",&n); for (int i = ;i < n;i++)
{
string aa,bb;
int v; cin >> aa >> bb; scanf("%d",&v); int x = get_num(aa),y = get_num(bb); if (g[x][y] == -) g[x][y] = g[y][x] = v;
else g[x][y] = g[y][x] = min(v,g[x][y]); a[i].x = x;
a[i].y = y;
a[i].v = g[x][y];
} for (int i = ;i <= num;i++) par[i] = i; scanf("%d",&lim); sort(a,a+n,cmp); for (int i = ;i < n;i++)
{
int x = a[i].x,y = a[i].y; if (x == || y == ) continue;
if (fin(x) == fin(y)) continue; ans += a[i].v; unit(x,y); flag[x][y] = flag[y][x] =;
} int minn[],tmp[]; memset(minn,inf,sizeof(minn)); for (int i = ;i <= num;i++)
{
int rt = fin(i); if (g[][i] != -)
{
if (g[][i] < minn[rt])
{
minn[rt] = g[][i];
tmp[rt] = i;
}
}
} for (int i = ;i <= num;i++)
{
if (minn[i] != inf)
{
du++;
flag[][tmp[i]] = flag[tmp[i]][] = ;
ans += minn[i];
}
} solve(); printf("Total miles driven: %d\n",ans); return ;
}

最新文章

  1. 关于 CSS 反射倒影的研究思考
  2. Thinking in java学习笔记之interface
  3. JAVA 多线程随笔 (一) 可见性和volatile关键字
  4. Nginx配置指定媒体类型文件强制下载
  5. MySQL Workbench “Error Code: 1175” 的解决方法
  6. Rational.Rose.Enterprise.v7.0 (2007)安装分享
  7. ImageMagick又一处命令执行
  8. 为什么anylase和scenaio中的平均响应时间差别会这么大?
  9. 20145120 《Java程序设计》第7周学习总结
  10. c#语法笔记
  11. Android 签名(6)编译时源码的签名
  12. diamond专题(四)—— 容灾机制
  13. C/C++四种退出线程的方法
  14. Oracle dataguard 正常切换和应急切换
  15. EntityFramework Core 2.0执行原始查询如何防止SQL注入?
  16. PopupWindowMenuUtil【popupwindow样式菜单项列表】
  17. django 加载css、js和图片记载不上
  18. 面向对象【day07】:面向对象使用场景(十)
  19. 在TOMCAT下配置工程的默认访问设置(转)
  20. .NET领域最为流行的IOC框架之一Autofac WebAPI2使用Autofac实现IOC属性注入完美解决方案 AutoFac容器初步

热门文章

  1. Python 基础语法复习
  2. Java 后端微信支付demo
  3. python自学日志--基础篇(1)
  4. 线程池的submit和execute方法区别
  5. ElasticSearch的安装
  6. pl/sql的介绍
  7. 20155306 2006-2007-2 《Java程序设计》第3周学习总结
  8. 201621123043 《Java程序设计》第1周学习总结
  9. webview缓存及跳转时截取url地址、监听页面变化
  10. PM2使用心得