测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。
当N为0时,输入结束,该用例不被处理。
对每个测试用例,在1行里输出最小的公路总长度。
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
3 5
解题思路:
并查集的变形题。和题目1545:奇怪的连通图其实性质差不多。当然也可以使用prim来做。这在另外一道题目1417:变型金刚中有所体现。
1、存储所有节点以及道路长度。
2、排序。
3、根据value值从小到大做并查集操作,发现道路个数count == n-1的时候就退出。
4、判断count是否小于n-1,如果成立的话,就说明所有道路并不能连通。否则输出道路长度。
C++使用的是并查集,Java使用的算法是prim,都给出代码。
C++ AC
#include<stdio.h> #include<algorithm> const int maxn = 102; const int maxm = 10002; int parent[maxn]; using namespace std; struct Node{ int start; int end; int value; }nodes[maxm]; int compare(Node node1 ,Node node2){ if(node1.value < node2.value){ return 1; } return 0; } int findParent(int f) { while (parent[f] != f) { f = parent[f]; } return f; } void unionTwo(int f, int t) { int a = findParent(f); int b = findParent(t); if (a == b) return; if (a > b) { parent[a] = b; } else { parent[b] = a; } } int main(){ int n; int m; while(scanf("%d",&n)!=EOF){ if(n == 0){ break; } int i = 0; m = (n-1)*n/2; for(i=0; i < m; i++){ scanf("%d%d%d" , &nodes[i].start, &nodes[i].end, &nodes[i].value); } sort(nodes,nodes+m,compare); for(i = 1; i < n+1 ; i++){ parent[i] = i; } int k = 0; int count = 0; for (i = 0; i < m; i++) { if (findParent(nodes[i].start) != findParent(nodes[i].end)) { unionTwo(nodes[i].start,nodes[i].end); k += nodes[i].value; count++; if(count == n-1){ break; } } } printf("%d\n",count < n-1 ? -1 : k); } return 0; } /************************************************************** Problem: 1017 User: wangzhenqing Language: C++ Result: Accepted Time:20 ms Memory:1140 kb ****************************************************************/
Java AC
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.StreamTokenizer; public class Main { /* * 1017 */ public static void main(String[] args) throws Exception { StreamTokenizer st = new StreamTokenizer (new BufferedReader(new InputStreamReader(System.in))); while (st.nextToken() != StreamTokenizer.TT_EOF) { int n = (int) st.nval; if (n == 0 ) { break; } int path[][] = new int[n+1][n+1]; for (int i = 1; i < n+1; i++) { for (int j = 1; j < n+1; j++) { path[i][j] = Integer.MAX_VALUE; } } int m = ((n-1)*n)/2; for (int i = 0; i < m; i++) { st.nextToken(); int a = (int) st.nval; st.nextToken(); int b = (int) st.nval; st.nextToken(); int d = (int) st.nval; if (path[a][b] > d ) { path[a][b] = d; path[b][a] = d; } } int minLen[] = new int[n+1]; int visit[] = new int[n+1]; for (int i = 1; i < n+1; i++) { minLen[i] = path[1][i]; } prime(path , minLen , visit ,n); } } private static void prime(int[][] path, int[] minLen, int[] visit, int n) { minLen[1] = 0; visit[1] = 1; int minj = 1; int resLen = 0; for (int i = 1; i < n; i++) { int min = Integer.MAX_VALUE; for (int j = 1; j < n+1; j++) { if (visit[j] == 0 && minLen[j] < min) { min = minLen[j]; minj = j; } } visit[minj] = 1; resLen += min; for (int j = 1; j < n+1; j++) { if (visit[j] == 0 && minLen[j] > path[minj][j]){ minLen[j] = path[minj][j]; } } } System.out.println(resLen); } } /************************************************************** Problem: 1017 User: wzqwsrf Language: Java Result: Accepted Time:240 ms Memory:23540 kb ****************************************************************/