题目描述:给定一个无向图,要求判断该图的最小生成树是否唯一,如果唯一的话输出最小生成树的权值,如果不唯一,输出Not Unique!
解题思路:要判断最小生成树是否唯一,可以求出次小生成树,看权值是否和最小生成树相等,如果相等的话说明最小生成树不唯一,否则说明最小生成树是唯一的,那么,只要求出次小生成树来就好办了。我用的是Kruskal算法求出最小生成树来,然后依次枚举这些树边并去掉,再求最小生成树,所得的这些值的最小值就是次小生成树的值,当然,前提是去掉一条树边以后,剩下的边可以形成次小生成树。
ps:这题糊里糊涂就过了,不知道是不是数据太弱,我总感觉自己考虑不周全,却不知道在哪里……
#include<iostream>
#include
<algorithm>
using namespace std;
int n,m,cas;
struct node
{
    
int u,v,w;
}edge[
10000];
int sum,num;
int mst,smst=0x7fffffff;//mst----最小生成树权值smst----次小生成树权值
bool v[10000],can[10001];//v记录是不是最小生成树的树边,can记录能否在求次小生成树时用到某边
int p[10001],rank[10001];
int Makeset()
{
    
int i;
    
for(i=1;i<=n;i++)
    {
        p[i]
=i;
        rank[i]
=0;
    }
    
return 0
}
int Find(int t)
{
    
if(t!=p[t])
    {
        p[t]
=Find(p[t]);
    }
    
return p[t];
}
bool cmp(node a,node b)
{
    
return a.w<b.w;
}
int Union(int a,int b)
{
    
int x=Find(a);
    
int y=Find(b);
    
if(rank[x]>rank[y])
    {
        p[y]
=x;
    }
    
else
    {
        p[x]
=y;
        
if(rank[x]==rank[y])
        {
            rank[y]
++;
        }
    }
    
return 0;
}
int Kruskal()
{
    num
=0;
    sum
=0;
    Makeset();
    
int i;
    
for(i=0;i<m;i++)
    {
        
if(Find(edge[i].u)!=Find(edge[i].v))
        {
            Union(edge[i].u,edge[i].v);
            sum
+=edge[i].w;
            v[i]
=1;
            num
++;
        }
        
if(num==n-1)
            
break;
    }
    
return sum;
}
int Sec_Kruskal()
{
    num
=0;
    sum
=0;
    
int i;
    Makeset();
    
for(i=0;i<m;i++)
    {
        
if(can[i])
        {
            
if(Find(edge[i].u)!=Find(edge[i].v))
            {
                Union(edge[i].u,edge[i].v);
                sum
+=edge[i].w;
                num
++;
            }
            
if(num==n-1)
                
break;
        }
    }
    
return sum;
}
int main()
{
    
int i,j; 
    scanf(
"%d",&cas);
    
while(cas--)
    {
        smst
=0x7fffffff;
        scanf(
"%d%d",&n,&m);
        
for(i=0;i<m;i++)
        {
            scanf(
"%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
        }
        memset(can,
1,sizeof(can));
        memset(v,
0,sizeof(v));
        sort(edge,edge
+m,cmp);
        mst
=Kruskal();
        
for(i=0;i<m;i++)
        {
            
if(v[i])
            {
                can[i]
=0;
                
int tmp=Sec_Kruskal();
                
if(tmp>=mst&&smst>tmp)//如果tmp<mst说明不能形成次小生成树
                {
                    smst
=tmp;
                }
                can[i]
=1;
            }
        }
        
if(mst==smst&&smst!=0)
        {
            printf(
"Not Unique!\n");
        }
        
else
        {
            printf(
"%d\n",mst);
        }
        
//printf("%d %d\n",mst,smst);
    }
    
//system("pause");
    return 0;
}