HDU:1863 畅通工程
来源:互联网 发布:钻石4c哪个最重要 知乎 编辑:程序博客网 时间:2024/05/18 15:05
畅通工程
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 27062 Accepted Submission(s): 11826
Problem Description
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。
Input
测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100 );随后的 N
行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
Output
对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。
Sample Input
3 31 2 11 3 22 3 41 32 3 20 100
Sample Output
3?解题思路:这个题目是给出N个村庄M条道路以及修这M条路的花费,求使N个村庄畅通的最小花费,很经典的最小生成树的题目,再学数据结构最小生成树的时候,老师讲到研究最小生成树的价值的时候,就举了修路的例子,印象还是很深刻的。我使用的算法是克鲁斯卡尔算法。#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<queue>#define inf 0x3f3f3f3fusing namespace std;int N,M; ///N条边,M个村庄int Map[202][202]; ///图///下面的一些行是为克鲁斯卡尔算法写的并查集操作。所用模板代码来自李春葆的数据结构课本typedef struct node{ int data; ///节点对应人的编号 int rrank; ///节点对应的秩 int parent; ///该节点对应的双亲的下标}UFSTree;void MAKE_SET(UFSTree t[],int n) ///初始化集合,将节点的双亲指向自己。{ int i; for(i = 1; i <= n; i++) { t[i].rrank = 0; t[i].parent = i; }}int FIND_SET(UFSTree t[],int x)///查找双亲{ if(x != t[x].parent) return (FIND_SET(t,t[x].parent)); else return x;}void UNION(UFSTree t[],int x,int y)///合并集合{ x = FIND_SET(t,x); y = FIND_SET(t,y); if(t[x].rrank > t[y].rrank) { t[y].parent = x; } else { t[x].parent = y; if(t[x].rrank == t[y].rrank) t[y].rrank++; }}///采用克鲁斯卡尔算法求最小生成树typedef struct{ int x; int y; int w; ///权值}Edge;Edge edge[10000]; ///用来存放边的数组bool cmp(Edge a,Edge b) ///从小到大进行排序{ return a.w < b.w;}int Kruskal(){ int i,j,u1,v1,sn1,sn2; UFSTree t[10000]; ///并查集树 sort(edge,edge+N,cmp); ///对路按权值进行从小到大排序 MAKE_SET(t,M); ///初始化并查集 i = 0; ///i用来统计当前已选中构成最小生成树的边数。 j = 0; int sum = 0; ///sum用来计算n个村庄畅通的最小花费 while(j < N) { u1 = edge[j].x; v1 = edge[j].y; sn1 = FIND_SET(t,u1);///找u1的祖先 sn2 = FIND_SET(t,v1);///找v1的祖先 if(sn1 != sn2) ///如果祖先不相等,那么说明它们不属于同一集合,将两个集合合并 { sum = sum + edge[j].w; i++; ///边数加上1 UNION(t,sn1,sn2); ///合并集合 } j++; ///接着看下一条边 } ///最小生成树的定义,有M个顶点,用M-1条边时M个顶点相通。因此如果最后能挑出N-1条边,则说明最小生成树存在,返回最小花费 if(i == M-1) return sum; else return -1; ///返回-1代表无解}int main(){ int i; while(~scanf("%d%d",&N,&M)) { if(N == 0) break; for(i = 0; i < N; i++) scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].w); int ans = Kruskal(); if(ans == -1) printf("?\n"); else printf("%d\n",ans); } return 0;}
0 0
- HDU 1863 畅通工程
- hdu 1863 畅通工程
- hdu 1863 畅通工程
- HDU 1863 畅通工程
- hdu 1863 畅通工程
- hdu 1863 畅通工程
- hdu 1863 畅通工程
- HDU 1863 畅通工程
- hdu 1863 畅通工程
- HDU 1863 畅通工程
- hdu 1863 畅通工程
- hdu 1863 畅通工程
- hdu 1863 畅通工程
- HDU-畅通工程-1863
- HDU 1863 畅通工程
- hdu 1863 畅通工程
- HDU 1863 畅通工程
- hdu 1863 畅通工程
- Android 安全使用HTTPS
- 算法概论 8.8
- 转载:android 各种xml资源的引用方式
- shell脚本编程
- js运算符
- HDU:1863 畅通工程
- 浅谈云计算
- 【Oracle】批量删除表
- Spring学习笔记之属性配置细节
- 使用模拟发送请求插件(postman)的一些问题
- linux网卡速率和双工模式的配置
- 如何写论文
- 1012. The Best Rank (25)
- linux 查看socket的连接状态