CTU 2012 Simon the Spider (Kruskal+枚举)
来源:互联网 发布:超强卸载软件 编辑:程序博客网 时间:2024/06/09 16:45
题目链接: http://contest.felk.cvut.cz/12prg/solved.html
题目大意: 给出一个无向图(不一定连通)
求连通所有点,从一顶点可以到任何顶点的路线
并且这条路线总长度减去两倍最长线段的值最小
也就是求总长度减去最长边的值最小的生成树
解题思路: 先把问题简化一下:
最小生成树总长度 — 最长边*2=n-1个顶点的生成树 — 最长边
使得上式的值最小,既使得左边的值最小,右边值最大!
开始想到的是删除一个点,求n-1个点的最小生成树
然后再找删除那个点连接这个生成树最长的边,WA了
证明:
删除一个点之后,有可能不存在n-1个点的生成树.
5 6
1 2 2
2 3 2
3 4 2
3 5 2
2 5 3
2 4 3
1 2 2
2 3 2
3 4 2
3 5 2
2 5 3
2 4 3
如,删除顶点2之后,顶点1就成了孤立点
正确的做法:
先将边从小到大排序,枚举每个顶点的最长的边
每个顶点总会有连接它的最长边,然后再找出其他n-1个点的最小生成树!
很容易证明到n-1个点的最小生成树的总长度肯定有下界 (最小值)
代码:
#include <stdio.h>#include <string.h>#include <stdlib.h>#define MAX 2101#define MAX_2 1000000#define INF 0x3f3f3f3ftypedef struct snode{ int x; int y; int s;}span;int father[MAX];span spantree[MAX_2];span longth[MAX];int comp(const void *a,const void *b){ span *pa=(span *)a; span *pb=(span *)b; return (pa->s)-(pb->s);}void Empty(int n) //并查集初始化{ int i; for(i=1;i<=n;i++) { father[i]=i; }}int Find(int x){ int s,j; s=x; while(x!=father[x]) { x=father[x]; } while(s!=x) { j=father[s]; father[s]=x; s=j; } return x;}void Union(int R1,int R2){ int r1,r2; r1=Find(R1); r2=Find(R2); if(r1!=r2) { father[r1]=r2; }}int main (){ int temp,t,n,m,i,j,min,pd,a,b; while(scanf("%d%d",&n,&m)!=EOF) { memset(longth,0,sizeof(longth)); for(j=0;j<m;j++) { scanf("%d%d%d",&spantree[j].x,&spantree[j].y,&spantree[j].s); if(spantree[j].s>longth[spantree[j].x].s) //找出每个顶点连接的最长边 { longth[spantree[j].x].s=spantree[j].s; longth[spantree[j].x].x=spantree[j].x; longth[spantree[j].x].y=spantree[j].y; } if(spantree[j].s>longth[spantree[j].y].s) //找出每个顶点连接的最长边 { longth[spantree[j].y].s=spantree[j].s; longth[spantree[j].y].x=spantree[j].y; longth[spantree[j].y].y=spantree[j].x; } } qsort(spantree,m,sizeof(spantree[0]),comp); //边从小到大排序 Empty(n); for(i=0;i<m;i++) { if(Find(spantree[i].x)!=Find(spantree[i].y)) { Union(spantree[i].x,spantree[i].y); } } for(i=1,pd=1;i<n;i++) { if(Find(father[i])!=Find(father[i+1])) //如果图不连通,打印"disconnected" { pd=0; break; } } if(pd) { for(j=1,min=INF;j<=n;j++) //枚举n次,每次取i顶点的最长边 { a=longth[j].x; b=longth[j].y; Empty(n); Union(a,b); temp=-(longth[j].s); //i顶点的最长边 for(i=0,t=1;i<m;i++) { if(t==n-1) //生成树已有n-1个顶点则退出 break; if(Find(spantree[i].x)!=Find(spantree[i].y)) { Union(spantree[i].x,spantree[i].y); t++; temp+=spantree[i].s; } } if(min>temp) min=temp; } printf("%d\n",min); } else printf("disconnected\n"); } return 0; }注:原创文章,转载请注明出处
- CTU 2012 Simon the Spider (Kruskal+枚举)
- CTU 2012 Gregory the Grasshopper (BFS)
- CTU 2011/CTU 2012 部分题解...
- HDU 1598 find the most comfortable road (枚举+Kruskal)
- HDU 1598 find the most comfortable road 枚举 + kruskal算法
- HDU 1598 find the most comfortable road (枚举+Kruskal)
- HDU 1598 find the most comfortable road (Kruskal + 枚举)
- 1poj2377(Kruskal||枚举)
- poj 3522 枚举+kruskal
- HDU-1598-find the most comfortable road(暴力枚举+Kruskal最小生成树)
- HDU 1598 find the most comfortable road 【枚举+(并查集)最小生成树Kruskal】
- HDU 1598 find the most comfortable road (枚举+Kruskal) 并查集
- hdu 1598 find the most comfortable road 枚举+最小成生树 kruskal 解题报告
- Spider
- spider
- Spider
- spider
- spider
- 虚拟机基础
- android手机与arm平台实现无线视频监控
- Java RMI
- peekmessage与GetMessage和VC之SendMessage与PostMessage的区别
- HDU 4362 单调队列优化DP
- CTU 2012 Simon the Spider (Kruskal+枚举)
- 软件项目顾问的20法则
- 从有n个元素的数组中找出出现次数大于n/3次的元素
- 北京邮电大学程序设计课程设计第二次实验Problem 4
- 2012-12-24 21:16 TI关于da8xx启动内核失败的网页
- Spring学习笔记(二)依赖注入Dependency Injection
- android学习阶段性总结
- 移植qt4.7.0到开发板的艰辛过程
- css3过渡