poj 1679 次小生成树
1 /* 2 题意:求次小生成树,权值和相同则输出字符串,否则输出值 3 4 题解:先求出最小生成树,然后枚举删除最小生成树的每一条边,找出新的最小生成树,即次小生成树,求出其中权值和最 5 小的一棵树,即可求解 6 */ 7 #include <cstdio> 8 #include <stdlib.h> 9 10 struct edge 11 { 12 int u,v; 13 bool flag; 14 int w; 15 }E[5005]; 16 int n,m; 17 int set[105]; 18 19 20 int cmp(const void *a,const void *b) 21 { 22 edge *c,*d; 23 c = (struct edge *)a; 24 d = (struct edge *)b; 25 return c->w-d->w; 26 } 27 28 int find(int r) 29 { 30 while (set[r] != r) 31 r = set[r]; 32 return set[r]; 33 } 34 35 int Kruskal(int rm_edge) 36 { 37 int i; 38 int f1,f2; 39 int count=1; 40 int ret = 0; 41 for(i=0;i<m;i++) 42 { 43 if(count == n) 44 break; 45 if(i == rm_edge) // 遇见选择删除的边则跳过 46 continue; 47 f1 = find(E[i].u); 48 f2 = find(E[i].v); 49 if(f1 == f2) 50 continue; 51 set[f1] = f2; 52 E[i].flag=true; 53 ret += E[i].w; 54 count++; 55 } 56 return ret; 57 } 58 59 int main(void) 60 { 61 int T; 62 int z,i; 63 int a,b,c; 64 int del[105],k; 65 66 scanf("%d",&T); 67 while(T--) 68 { 69 scanf("%d%d",&n,&m); 70 // 第一次先找出最小生成树 71 for(int i=1; i<=n; i++) 72 set[i] = i; 73 for(i=0;i<m;i++) 74 { 75 scanf("%d%d%d",&a,&b,&c); 76 E[i].u=a; 77 E[i].v=b; 78 E[i].w=c; 79 E[i].flag = false; 80 } 81 82 qsort(E,m,sizeof(E[0]),cmp); 83 int ans = Kruskal(-1); 84 int temp=0; 85 for(i=1; i<=n; i++) 86 if(set[i]==i) 87 temp++; 88 if(temp>1) 89 { 90 printf("0\n"); 91 continue; 92 } 93 k=0; 94 for(i=0;i<m;i++) 95 if(E[i].flag) 96 del[k++]=i; 97 98 bool flag = false; 99 for(z=0;z<k;z++) 100 { 101 for(int i=1; i<=n; i++) 102 set[i] = i; 103 int tmp = Kruskal(del[z]); // 依次删除最小生成树的边来再次生成树 104 temp = 0; 105 for(i=1; i<=n; i++) 106 if(set[i] == i) 107 temp++; 108 if(temp > 1) 109 continue; 110 111 if(tmp == ans) 112 { 113 flag=true; 114 break; 115 } 116 } 117 118 if(flag) 119 printf("Not Unique!\n"); 120 else 121 printf("%d\n",ans); 122 } 123 return 0; 124 }