九度oj 题目1347:孤岛连通工程
- 题目描述:
-
现在有孤岛n个,孤岛从1开始标序一直到n,有道路m条(道路是双向的,如果有多条道路连通岛屿i,j则选择最短的那条),请你求出能够让所有孤岛都连通的最小道路总长度。
- 输入:
-
数据有多组输入。
每组第一行输入n(1<=n<=1000),m(0<=m<=10000)。
接着m行,每行输入一条道路i j d(0<=d<=1000),(i,j表示岛屿序号,d表示道路长度)。
- 输出:
-
对每组输入输出一行,如果能连通,输出能连通所有岛屿的最小道路长度,否则请输出字符串"no"。
- 样例输入:
-
3 5 1 2 2 1 2 1 2 3 5 1 3 3 3 1 2 4 2 1 2 3 3 4 1
- 样例输出:
-
3 no
求最小生成树1 #include <cstdio> 2 #include <algorithm> 3 #define max_v 1002 4 #define max_m 10002 5 struct Edge{ 6 int from, to, dis; 7 }; 8 int par[max_v]; 9 int rank[max_v]; 10 11 int cmp(const void *a, const void *b) { 12 Edge at = *(Edge *)a; 13 Edge bt = *(Edge *)b; 14 return at.dis - bt.dis; 15 } 16 int ini(int N) { 17 for(int i = 0; i <= N; i++) { 18 par[i] = i; 19 rank[i] = 0; 20 } 21 } 22 int find(int t) { 23 if(t == par[t]) { 24 return t; 25 } 26 else { 27 return par[t] = find(par[t]); 28 } 29 } 30 31 Edge e[max_m]; 32 int n, m; 33 int main(int argc, char const *argv[]) 34 { 35 freopen("input.txt","r",stdin); 36 while(scanf("%d %d",&n,&m) != EOF) { 37 for(int i = 0; i < m; i++) { 38 scanf("%d %d %d",&e[i].from, &e[i].to, &e[i].dis); 39 } 40 qsort(e, m, sizeof(Edge), cmp); 41 int ans = 0; 42 int cnt = 0; 43 ini(n); 44 for(int i = 0; i < m; i++) { 45 int a = e[i].from; 46 int b = e[i].to; 47 int c = e[i].dis; 48 //printf("%d %d %d\n",a,b,c); 49 a = find(a); 50 b = find(b); 51 if(a == b) { 52 continue; 53 } 54 if(a != b) { 55 ans = ans + c; 56 if(rank[a] < rank[b]) { 57 par[a] = b; 58 } 59 else { 60 par[b] = a; 61 rank[a]++; 62 } 63 cnt++; 64 if(cnt == n-1) { 65 break; 66 } 67 } 68 } 69 if(cnt == n-1) { 70 printf("%d\n",ans); 71 } 72 else { 73 puts("no"); 74 } 75 } 76 return 0; 77 }