题目描述:给一个图,判断最小生成树是否唯一,n<=100
解题思路:题意简单明了,最小生成树模板都会敲,网上也没有什么特别好的方法,都是最简单暴力枚举,枚举的前提,有可以取代它的边。
最小生成树特征:n个节点,n-1条边。
不唯一定义:如果最小生成树的其中一条边或者几条边可以被其他边所取代,最后生成的最小生成树权重一样,就表明最小生成树不唯一。这个取代过程,怎样控制?直接的方法,标识,把最小生成树所有的边都标识。然后枚举去掉标识中一条边,构造出的最小生成树是否和最小生成树权重一样。但是很显然,我们做了很多无用功,有一些边是无法取代的,怎么判断哪些边是无法取代的?最简单的方法,能否找到一个权重一样的边来取代它。如果有一条权重一样,则去掉这条边,构造最小生成树,这就是枚举的过程。
#include<stdio.h>
#include<algorithm>
#include <vector>
using namespace std;
#include <string.h>
int book[110];
int n,m,father[110];
struct node
{
int x;
int y;
int value;
} Q[11000];
bool cmp(node a,node b)
{
return a.value<b.value;
}
void init()
{
for(int i=0; i<=n; i++)
father[i] = -1;
}
int find(int x)
{
if(father[x]==-1)
return x;
return father[x]=find(father[x]); //这个点可能造成超时
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&n,&m);
memset(book,0,sizeof(book));
for(int i=0; i<m; i++)
scanf("%d %d %d",&Q[i].x,&Q[i].y,&Q[i].value);
sort(Q,Q+m,cmp);
init();
int kmp = 0,tmp = 0,flag=0;
for(int i=0; i<m; i++)
{
int tx = find(Q[i].x);
int ty = find(Q[i].y);
if(tx!=ty)
{
father[tx] = ty;
tmp += Q[i].value;
book[i] = 1 ;
kmp++;
}
if(kmp == n -1)
break;
}
for(int i=0; i<m; i++)
{
if(book[i]==1&&Q[i+1].value==Q[i].value&&i+1<m)
{
init();
int kmp =0,term = 0;
for(int j=0; j<m; j++)
{
if(i==j) continue;
int tx = find(Q[j].x);
int ty = find(Q[j].y);
if(tx!=ty)
{
father[tx]=ty;
term += Q[j].value;
kmp++;
}
if(kmp==n-1)
break;
}
if(term == tmp)
{
flag=1;
break;
}
}
}
if(flag)
printf("Not Unique!\n");
else printf("%d\n",tmp);
}
return 0;
}