POJ 1679 The Unique MST (次小生成树)
题目链接:http://poj.org/problem?id=1679
有t组数据,给你n个点,m条边,求是否存在相同权值的最小生成树(次小生成树的权值大小等于最小生成树)。
先求出最小生成树的大小,把最小生成树的边存起来。然后分别枚举最小生成树上的每条边,除了这条边,其他边是否能生成最小生成树,若生成树的权值等于原来最小生成树的权值,则不唯一,否则输出最小生成树的权值。这里我用kruskal比较方便。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 using namespace std; 7 const int MAXN = 105; 8 const int INF = 1e9; 9 struct edge { 10 int u , v , cost; 11 }a[MAXN * MAXN]; 12 typedef pair <int , int> P; 13 int par[MAXN] , f; 14 bool vis[MAXN][MAXN]; 15 vector <P> G; 16 17 void init(int n) { 18 for(int i = 1 ; i <= n ; i++) { 19 par[i] = i; 20 } 21 memset(vis , false , sizeof(vis)); 22 f = 0; 23 G.clear(); 24 } 25 26 bool cmp(edge a , edge b) { 27 return a.cost < b.cost; 28 } 29 30 int Find(int n) { 31 if(par[n] == n) 32 return n; 33 return (par[n] = Find(par[n])); 34 } 35 36 int kruskal(int m , int n) { 37 int res = 0 , cont = n; 38 for(int i = 1 ; i <= m ; i++) { 39 if(cont == 1) 40 break; 41 else if(vis[a[i].u][a[i].v]) 42 continue; 43 int u = Find(a[i].u) , v = Find(a[i].v); 44 if(u != v) { 45 if(!f) { 46 G.push_back(P(a[i].u , a[i].v)); // f等于0的时候是求最小生成树的时候,存边操作 47 } 48 par[u] = v; 49 res += a[i].cost; 50 cont--; 51 } 52 } 53 if(cont == 1) 54 return res; 55 return INF; 56 } 57 58 int main() 59 { 60 int t , n , m , u , v , w; 61 scanf("%d" , &t); 62 while(t--) { 63 scanf("%d %d" , &n , &m); 64 init(n); 65 for(int i = 1 ; i <= m ; i++) { 66 scanf("%d %d %d" , &u , &v , &w); 67 a[i].u = u , a[i].v = v , a[i].cost = w; 68 } 69 sort(a + 1 , a + m + 1 , cmp); 70 int res = kruskal(m , n) , check = 0; 71 f++; 72 for(int i = 0 ; i < G.size() ; i++) { 73 for(int j = 1 ; j <= n ; j++) { 74 par[j] = j; 75 } 76 vis[G[i].first][G[i].second] = true; 77 if(res == kruskal(m , n)) { 78 check = 1; 79 break; 80 } 81 vis[G[i].first][G[i].second] = false; 82 } 83 if(check) { 84 printf("Not Unique!\n"); 85 } 86 else { 87 printf("%d\n" , res); 88 } 89 } 90 }