Input测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。
当N为0时,输入结束,该用例不被处理。
Output对每个测试用例,在1行里输出最小的公路总长度。
Sample Input
3 1 2 1 1 3 2 2 3 4 4 1 2 1 1 3 4 1 4 1 2 3 3 2 4 2 3 4 5 0
Sample Output
3 5 Huge input, scanf is recommended.
- 并查集的
#include<cstdio> #include<iostream> #include<algorithm> #include<string> #include<cstring> #include<map> using namespace std; int n,bc[110],ans; struct P { int a, b, c; bool operator<(const P&a)const { return c < a.c; } }s[5005]; int Find(int i) { if (bc[i] == i) return i; else { bc[i] = Find(bc[i]); return bc[i]; } } void Join(int a, int b, int idx) { int x = Find(a), y = Find(b); if (x != y) { bc[y] = x; ans += s[idx].c; } } int main() { //freopen("in.txt", "r", stdin); while (scanf("%d",&n)&&n) { int m = (n*(n - 1)) / 2; ans = 0; for (int i = 1; i <= n; i++) bc[i] = i; for (int i = 0; i < m; i++) { scanf("%d %d %d", &s[i].a, &s[i].b, &s[i].c); } sort(s, s + m); for (int i = 0; i < m; i++) Join(s[i].a, s[i].b, i); printf("%d\n", ans); } return 0; }
- 最小生成树
#include<cstdio> #include<iostream> #include<algorithm> #include<string> #include<cstring> #include<map> using namespace std; #define inf 0x3f3f3f int n,ans; int edge[110],M[110][110]; int main() { //freopen("in.txt", "r", stdin); while (scanf("%d",&n)&&n) { memset(M, inf, sizeof(M)); int m = (n*(n - 1)) / 2; ans = 0; for (int i = 0; i < m; i++) { int a, b, c; scanf("%d %d %d", &a, &b, &c); M[a][b] = M[b][a] = c; } bool S[110]; memset(S, 0, sizeof(S)); for (int i = 2; i <= n; i++) edge[i] = M[1][i]; S[1] = 1; for (int i = 1; i <= n-1; i++) { int v=-1, maxl = inf; for (int j = 2; j <= n; j++) if (!S[j]&&maxl > edge[j]) { v = j; maxl = edge[j]; } if (v == -1) break; S[v] = 1; ans += edge[v]; for (int j = 2; j <= n; j++) if (!S[j] && M[v][j] < edge[j]) { edge[j] = M[v][j]; } } printf("%d\n", ans); } return 0; }