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 }

 

posted @ 2014-04-05 22:22  辛力啤  阅读(145)  评论(0编辑  收藏  举报