Num 31 : HDOJ : 1863 畅通工程 [ kruskal( 克鲁斯卡尔 )算法 ] [ 最小生成树 ]
2015-08-11 10:50
821 查看
克鲁斯卡尔算法是用来解决最小生成树问题的算法,我们先来看看什么是生成树吧:
生成树:
给定一个无向图,如果它某个子图中任意两个顶点都互相连通并且是一颗树( 一个根节点,多个父节点 ).
如图:( 图片摘自百度 )
易知生成树不唯一;
最小生成树:
如果边上有权值,那么使得权值和最小的生成树叫做最小生成树。
例:如图:
两种常用的构造最小生成树的方法:
1. 克鲁斯卡尔算法(从边入手);
2. 普里姆算法(从点入手);
这里仅介绍克鲁斯卡尔算法;
Kruskal算法思想:
按照边的权值的顺序从小到大查看一遍,如果不产生环(重边),就把当前这条边加入到生成树中。
步骤如下:
1. 建立一个结构体数组,分别存储各点的开端,结尾,权重;
2. 按照边的从小到大排序;
3. 按边从小到大开始游历,若不产生环或重边,加入到生成树中;
题目:
Total Submission(s): 21252 Accepted Submission(s): 9147
[align=left]Problem Description[/align]
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。
[align=left]Input[/align]
测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100 );随后的 N
行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
[align=left]Output[/align]
对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。
[align=left]Sample Input[/align]
[align=left]Sample Output[/align]
题目分析:
首先这是一道很明显的最小生成树问题;
1. 需要对数据按照成本从小到大排序;
2. 是最小生成树的时候,应该有m个城镇有m-1条边;
3. 所有城镇只有一个根节点;
AC代码:
关键算法:
1. 定义一个结构体数组便于存放起始,结束,价值( start,end,value ):
2.
经典的并查集算法,并增加了判断是否成环( 成环返回0,并不加入;加入返回1 ):
3. 计算并加入生成树:
4.
判断根节点个数:
生成树:
给定一个无向图,如果它某个子图中任意两个顶点都互相连通并且是一颗树( 一个根节点,多个父节点 ).
如图:( 图片摘自百度 )
易知生成树不唯一;
最小生成树:
如果边上有权值,那么使得权值和最小的生成树叫做最小生成树。
例:如图:
两种常用的构造最小生成树的方法:
1. 克鲁斯卡尔算法(从边入手);
2. 普里姆算法(从点入手);
这里仅介绍克鲁斯卡尔算法;
Kruskal算法思想:
按照边的权值的顺序从小到大查看一遍,如果不产生环(重边),就把当前这条边加入到生成树中。
步骤如下:
1. 建立一个结构体数组,分别存储各点的开端,结尾,权重;
2. 按照边的从小到大排序;
3. 按边从小到大开始游历,若不产生环或重边,加入到生成树中;
题目:
畅通工程
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 21252 Accepted Submission(s): 9147
[align=left]Problem Description[/align]
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。
[align=left]Input[/align]
测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100 );随后的 N
行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
[align=left]Output[/align]
对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。
[align=left]Sample Input[/align]
3 3 1 2 1 1 3 2 2 3 4 1 3 2 3 2 0 100
[align=left]Sample Output[/align]
3 ?
题目分析:
首先这是一道很明显的最小生成树问题;
1. 需要对数据按照成本从小到大排序;
2. 是最小生成树的时候,应该有m个城镇有m-1条边;
3. 所有城镇只有一个根节点;
AC代码:
<span style="font-size:12px;">#include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> int per[110]; int mark[110]; struct Rode { int start; int end; int value; }rode[10000]; void init() { for(int i=1; i<=110 ; i++) per[i]=i; } int find(int x) { int r=x; while(per[r]!=r) r=per[r]; int i,j; i=x; while(i!=r) { j=per[i]; per[i]=r; i=j; } return r; } int join(int x,int y) { int fx,fy; fx=find(x); fy=find(y); if(fx!=fy) { per[fx]=fy; return 1; } else return 0; } int cmp(const void *a ,const void *b) { return (*(Rode *)a).value-(*(Rode *)b).value; } int main() { int i,n,m,num,count,numb; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0) break; for(i=0; i<n; i++) scanf("%d%d%d",&rode[i].start,&rode[i].end,&rode[i].value); qsort(rode,n,sizeof(rode[0]),cmp); count=0;num=0;init();memset(mark,0,sizeof(mark));numb=0; for(i=0; i<n; i++) if(join(rode[i].start,rode[i].end)==1) { count+=rode[i].value;mark[i]=1;numb++; } for(i=0; i<n; i++) if(per[i]==i&&mark[i]) num++; if(num==1&&numb==m-1) printf("%d\n",count); else printf("?\n"); } return 0; }</span>
关键算法:
1. 定义一个结构体数组便于存放起始,结束,价值( start,end,value ):
<span style="font-size:12px;">struct Rode { int start; int end; int value; }rode[10000];</span>
2.
经典的并查集算法,并增加了判断是否成环( 成环返回0,并不加入;加入返回1 ):
<span style="font-size:12px;">void init() { for(int i=1; i<=110 ; i++) per[i]=i; } int find(int x) { int r=x; while(per[r]!=r) r=per[r]; int i,j; i=x; while(i!=r) { j=per[i]; per[i]=r; i=j; } return r; } int join(int x,int y) { int fx,fy; fx=find(x); fy=find(y); if(fx!=fy) { per[fx]=fy; return 1; } else return 0; }</span>
3. 计算并加入生成树:
<span style="font-size:12px;">for(i=0; i<n; i++) if(join(rode[i].start,rode[i].end)==1) { count+=rode[i].value;mark[i]=1;numb++; }</span>
4.
判断根节点个数:
if(per[i]==i&&mark[i]) num++;
相关文章推荐
- X的追求道路 SDUT 3027
- hdoj 1863 畅通工程 【最小生成树】
- 21-IO流-15-IO流(字符流-缓冲区-复制文本文件)
- 21-IO流-16-IO流(字符流-缓冲区-自定义MyBufferedReader-read方法)
- 本地推送的使用方法
- 手机端开发
- 浅析Android的横竖屏切换
- hdu 4109(拓扑排序 关键路径)
- SSL心跳漏洞的检测
- IOS开发 @property中assign、copy 、retain等关键字的理解
- 算法竞赛入门经典: 第三章 数组和字符串 3.3蛇形填数
- 21-IO流-14-IO流(字符流-缓冲区-BufferedReader-readLine方法原理)
- Oracle 12C -- Invisible Columns
- Error: L6218E: Undefined symbol main (referred from entry9a.o).
- Algorithms-94.Binary Tree Inorder Traversal
- ACM Computer Factory
- 21-IO流-13-IO流(字符流-缓冲区-BufferedReader)
- php5.4和apache2.4.9不在同一台服务器的配置注意事项
- OR1200数据Cache运用情景分析
- php webservice soap