题目链接:http://poj.org/problem?id=1751
题意是给你n个点的坐标,然后给你m对点是已经相连的,问你还需要连接哪几对点,使这个图为最小生成树。
这里用kruskal不会超时,用prim应该会超时,特别注意在输入的时候不要多组输入,否则会TLE。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 using namespace std; 7 const int MAXN = 755; 8 struct edge { 9 int u , v , cost; 10 }a[MAXN * MAXN]; 11 int x[MAXN] , y[MAXN] , cont , par[MAXN] , cnt , f , ans[MAXN * 2]; 12 bool vis[MAXN][MAXN]; 13 14 void init(int n) { 15 for(int i = 1 ; i <= n ; i++) { 16 par[i] = i; 17 } 18 memset(vis , false , sizeof(vis)); 19 cont = 0; 20 cnt = n; 21 } 22 23 int Find(int n) { 24 if(n == par[n]) 25 return n; 26 return (par[n] = Find(par[n])); 27 } 28 29 bool cmp(edge a , edge b) { 30 return a.cost < b.cost; 31 } 32 33 int kruskal() { 34 for(int i = 1 ; i <= cont ; i++) { 35 if(cnt == 1) 36 break; 37 int u = Find(a[i].u) , v = Find(a[i].v); 38 if(u != v) { 39 ans[f++] = a[i].u; 40 ans[f++] = a[i].v; 41 par[u] = v; 42 cnt--; 43 } 44 } 45 } 46 47 int main() 48 { 49 int n , m , u , v; 50 scanf("%d" , &n); 51 { 52 init(n); 53 for(int i = 1 ; i <= n ; i++) { 54 scanf("%d %d" , x + i , y + i); 55 } 56 scanf("%d" , &m); 57 while(m--) { 58 scanf("%d %d" , &u , &v); 59 u = Find(u) , v = Find(v); 60 vis[u][v] = vis[v][u] = true; 61 if(u != v) { 62 par[u] = v; 63 cnt--; 64 } 65 } 66 for(int i = 1 ; i <= n ; i++) { 67 for(int j = 1 ; j < i ; j++) { 68 if(vis[i][j]) 69 continue; 70 cont++; 71 a[cont].u = j , a[cont].v = i; 72 a[cont].cost = (x[i] - x[j])*(x[i] - x[j]) + (y[i] - y[j])*(y[i] - y[j]); 73 } 74 } 75 sort(a + 1 , a + cont + 1 , cmp); 76 f = 0; 77 kruskal(); 78 for(int i = 0 ; i < f ; i += 2) { 79 printf("%d %d " , ans[i] , ans[i + 1]); 80 } 81 } 82 }