1. 程式人生 > >POJ 1679 The Unique MST(判斷最小生成樹是否唯一)

POJ 1679 The Unique MST(判斷最小生成樹是否唯一)

connect col pro case pac str other sid 一次

題目鏈接:

http://poj.org/problem?id=1679

Description

Given a connected undirected graph, tell if its minimum spanning tree is unique.

Definition 1 (Spanning Tree): Consider a connected, undirected graph G = (V, E). A spanning tree of G is a subgraph of G, say T = (V‘, E‘), with the following properties:
1. V‘ = V.
2. T is connected and acyclic.

Definition 2 (Minimum Spanning Tree): Consider an edge-weighted, connected, undirected graph G = (V, E). The minimum spanning tree T = (V, E‘) of G is the spanning tree that has the smallest total cost. The total cost of T means the sum of the weights on all the edges in E‘.

Input

The first line contains a single integer t (1 <= t <= 20), the number of test cases. Each case represents a graph. It begins with a line containing two integers n and m (1 <= n <= 100), the number of nodes and edges. Each of the following m lines contains a triple (xi, yi, wi), indicating that xi and yi are connected by an edge with weight = wi. For any two nodes, there is at most one edge connecting them.

Output

For each input, if the MST is unique, print the total cost of it, or otherwise print the string ‘Not Unique!‘.

Sample Input

2
3 3
1 2 1
2 3 2
3 1 3
4 4
1 2 2
2 3 2
3 4 2
4 1 2

Sample Output

3
Not Unique!

Source

POJ Monthly--2004.06.27 srbga@POJ
  1 /*
  2 問題
  3 判斷最小生成樹是否唯一
  4 
  5 解題思路
  6 利用克魯斯卡爾算法計算出最小花費和標記每一條邊,每次刪除一條標記邊,再進行一次克魯斯卡爾,如果能夠生成最小生
7 成樹而且最小代價相同,說明最小生成樹不唯一,否則說明最小生成樹是唯一的輸出最小花費。 8 */ 9 #include<cstdio> 10 #include<algorithm> 11 12 using namespace std; 13 14 struct EDGE{ 15 int u,v,w,f; 16 }edge[10010]; 17 int n,m; 18 int fa[110]; 19 int cmp(struct EDGE a,struct EDGE b){ 20 return a.w<b.w; 21 } 22 int kruskal1(); 23 int kruskal2(); 24 int merge(int u,int v); 25 int getf(int v); 26 int ok(int ans); 27 28 int main() 29 { 30 int T,i; 31 scanf("%d",&T); 32 33 while(T--){ 34 scanf("%d%d",&n,&m); 35 for(i=0;i<m;i++){ 36 scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w); 37 edge[i].f=0; 38 } 39 40 sort(edge,edge+m,cmp); 41 /*for(i=0;i<m;i++){ 42 printf("%d %d %d %d\n",edge[i].u,edge[i].v,edge[i].w,edge[i].f); 43 }*/ 44 45 int mina=kruskal1(); 46 //printf("%d\n",mina); 47 48 if(ok(mina)) 49 printf("%d\n",mina); 50 else 51 printf("Not Unique!\n"); 52 } 53 return 0; 54 } 55 56 int ok(int ans){ 57 int temp,i; 58 for(i=0;i<m;i++){ 59 if(edge[i].f){ 60 //printf("刪去 %d 這條邊\n",i); 61 edge[i].f=-1; 62 temp=kruskal2(); 63 if(temp == ans)//構成最小生成樹並且最小代價相同 64 return 0; 65 66 edge[i].f=1; 67 } 68 } 69 return 1; 70 } 71 72 int kruskal1() 73 { 74 int i; 75 for(i=1;i<=n;i++) 76 fa[i]=i; 77 int c=0,sum=0; 78 79 for(i=0;i<m;i++){ 80 if(merge(edge[i].u,edge[i].v)){ 81 c++; 82 sum += edge[i].w; 83 edge[i].f=1; 84 } 85 if(c == n-1) 86 break; 87 } 88 return sum; 89 } 90 91 int kruskal2() 92 { 93 int i; 94 for(i=1;i<=n;i++) 95 fa[i]=i; 96 int c=0,sum=0; 97 98 for(i=0;i<m;i++){ 99 if(edge[i].f >= 0 && merge(edge[i].u,edge[i].v)){ 100 //printf("使用 %d 這條邊 %d %d %d\n",i,edge[i].u,edge[i].v,edge[i].w); 101 c++; 102 sum += edge[i].w; 103 } 104 if(c == n-1) 105 break; 106 } 107 108 if(c == n-1) 109 return sum; 110 else 111 return -1; 112 } 113 114 int merge(int u,int v){ 115 int t1=getf(u); 116 int t2=getf(v); 117 if(t1 != t2){ 118 fa[t2]=t1; 119 return 1; 120 } 121 return 0; 122 } 123 124 int getf(int v){ 125 return fa[v] == v ? v : fa[v]=getf(fa[v]); 126 }

POJ 1679 The Unique MST(判斷最小生成樹是否唯一)