poj 1639 Picnic Planning 度限制mst
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 ;
}
poj 1639 Picnic Planning 度限制mst的更多相关文章
- POJ 1639 Picnic Planning 最小k度生成树
Picnic Planning Time Limit: 5000MS Memory Limit: 10000K Total Submissions:11615 Accepted: 4172 D ...
- POJ 1639 Picnic Planning:最小度限制生成树
题目链接:http://poj.org/problem?id=1639 题意: 给你一个无向图,n个节点,m条边,每条边有边权. 让你求一棵最小生成树,同时保证1号节点的度数<=k. 题解: 最 ...
- [POJ 1639] Picnic Planning
[题目链接] http://poj.org/problem?id=1639 [算法] 首先,我们可以用深度优先遍历求出1号节点去除后有几个联通块 设共有T个联通块,若T > K则无解,否则 : ...
- POJ 1639 Picnic Planning(最小度限制生成树)
Description The Contortion Brothers are a famous set of circus clowns, known worldwide for their inc ...
- poj 1639 最小k度限制生成树
题目链接:https://vjudge.net/problem 题意: 给各位看一下题意,算法详解看下面大佬博客吧,写的很好. 参考博客:最小k度限制生成树 - chty - 博客园 https:/ ...
- K度限制MST poj 1639
/* k度限制MST:有一个点的度<=k的MST poj 1639 要求1号点的度不超过k 求MST 我们先把1号点扔掉 跑MST 假设有sum个连通分支 然后把这sum个分支连到1上 就得到了 ...
- poj1639,uva1537,uvalive2099,scu1622,fzu1761 Picnic Planning (最小限制生成树)
Picnic Planning Time Limit: 5000MS Memory Limit: 10000K Total Submissions: 10742 Accepted: 3885 ...
- POJ1639 - Picnic Planning
原题链接 Description 给出一张个点的无向边权图并钦定点,求使得点的度不超过的最小生成树. Solution 首先无视掉与相连的所有边,原图会变成若干互不连通的个块.对每个块分别求MST,再 ...
- 【POJ 1639】 Picnic Planning (最小k度限制生成树)
[题意] 有n个巨人要去Park聚会.巨人A和先到巨人B那里去,然后和巨人B一起去Park.B君是个土豪,他家的停车场很大,可以停很多车,但是Park的停车场是比较小.只能停k辆车.现在问你在这个限制 ...
随机推荐
- 读取pdf内容分页和全部
//读取pdf 全部内容public static String topdffile(String pdffile){ StringBuffer result = new StringBuffer() ...
- C++模板类与Qt信号槽混用
一.正文 目前正在做一个视频处理相关的项目.项目的技术栈是这样的,UI层采用Qt来实现基本的数据展示和交互,底层音视频采用的是一套基于FFmpeg的视频处理框架.这是一套类似Microsoft Med ...
- 关于try catch finally
一.try catch finally的初步理解 首先,我们什么时候要用到try/catch和finally? --已知执行的代码有可能有异常的情况下 try { //这里执行的代码如果出现异常,则立 ...
- Xss问题解决方案
xss跨站脚本攻击问题最主要是呈现在html页面的脚本被执行导致的结果,可分为两个方便作屏蔽 后台屏蔽 在前端上传的各个参数后,对其进行转义后再保存至数据库,属于暴力式转义,一般不建议.下面是写的例子 ...
- Mycat 分片规则详解--一致性hash分片
实现方式:基于hash算法的分片中,算法内部是把记录分片到一种叫做"bucket"(hash桶)的内部算法结构中的,然后hash桶与实际的分片节点一一对应,从此实现了分片.路由的功 ...
- 前端Blob对二进制流数据的处理方式
var xhr = new XMLHttpRequest(); xhr.open("post", "/login/getCaptcher?t=" + Math. ...
- http,socks4,socks5代理的区别
HTTP代理 能够代理客户机的HTTP访问,主要是代理浏览器访问网页,它的端口一般为80.8080.3128等: SOCKS代理 SOCKS代理与其他类型的代理不同,它只是简单地传递数据包,而并不关心 ...
- 源码实现 --> strrev
字符串的顺序反序 函数 char *strrev(char *string); 将字符串string中的字符顺序颠倒过来. NULL结束符位置不变. 返回调整后的字符串的指针. 源码 //其基于的思想 ...
- 爬虫(scrapy第一篇)
---------------------------------------------------------------------------------------------------- ...
- 关于使用Unity开发Kinect时出现的Runtime Error错误的解决方式
一.开发环境: 1. 硬件:Kinect 2.0 2. 操作系统:Windows10 3. Unity版本:5.x以上 4. Kinect SDK:KinectSDK-v2.0_1409 5. Kin ...