九度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
思路:
利用并查集求最小生成树,如果失败则输出no
代码:
#include <stdio.h> #include <stdlib.h> #define N 1000 #define M 10000 typedef struct node { int x; int y; int d; } ROAD; int n; int pre[N+1]; int count[N+1]; int num; void init() { for (int i=1; i<=n; i++) { pre[i] = i; count[i] = 1; } num = n; } int find(int i) { while (i != pre[i]) i = pre[i]; return i; } int combine(int i, int j) { int a = find(i); int b = find(j); if (a != b) { if (count[a] > count[b]) { pre[b] = a; count[a] += count[b]; count[b] = 0; } else { pre[a] = b; count[b] += count[a]; count[a] = 0; } num --; return 1; } else return 0; } int cmp(const void *a, const void *b) { return (((ROAD *)a)->d > ((ROAD *)b)->d) ? 1 : -1; } int main(void) { int m, i; ROAD r[M]; int sum; while (scanf("%d%d", &n, &m) != EOF) { for(i=0; i<m; i++) scanf("%d%d%d", &r[i].x, &r[i].y, &r[i].d); qsort(r, m, sizeof(r[0]), cmp); init(); sum = 0; for(i=0; i<m; i++) { if(combine(r[i].x, r[i].y)) sum += r[i].d; if (num == 1) break; } if (num > 1) printf("no\n"); else printf("%d\n", sum); } return 0; } /************************************************************** Problem: 1347 User: liangrx06 Language: C Result: Accepted Time:910 ms Memory:972 kb ****************************************************************/
编程算法爱好者。