首页 > 代码库 > POJ 1679 The Unique MST

POJ 1679 The Unique MST

判断最小生成树是否唯一。


先扫一遍边,找出相等的边并标记 vis;


然后生成最小生成树,总权值为 ans,并记录下哪些边在第一次生成中使用了。use;


最后扫描所有边,有相等的,并且使用的边。把它标记为删除 del;然后生成最小生成树。

如果跟第一颗树权值一样,表明生成树不是唯一的。


#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
#include<queue>
#include<map>
#include<stack>
#include<iostream>
#include<list>
#include<set>
#include<cmath>
#define INF 0x7fffffff
#define eps 1e-6
using namespace std;
int n,m;
int fa[101];
struct lx
{
    int u,v,len;
} l[101*50];
int father(int x)
{
    if(x!=fa[x])
        return fa[x]=father(fa[x]);
}
bool cmp(lx a,lx b)
{
    return a.len<b.len;
}
bool vis[101*50];
bool use[101*50];
bool del[101*50];
int Kruskal(bool flag)
{
    for(int i=0; i<=n; i++)
        fa[i]=i;
    int point=1,ans=0;
    for(int i=0; i<m; i++)
    {
        if(del[i])continue;
        int u=father(l[i].u);
        int v=father(l[i].v);
        if(u==v)continue;
        fa[u]=v;
        point++;
        if(flag)use[i]=1;
        ans+=l[i].len;
        if(point>=n)break;
    }
    return ans;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0; i<m; i++)
            scanf("%d%d%d",&l[i].u,&l[i].v,&l[i].len);
        sort(l,l+m,cmp);
        memset(vis,0,sizeof(vis));
        memset(use,0,sizeof(use));
        memset(del,0,sizeof(del));
        for(int i=0; i<m-1; i++)
            if(l[i].len==l[i+1].len)vis[i]=vis[i+1]=1;

        int bt1=Kruskal(1);
        bool flag=1;

        for(int i=0; i<m; i++)
        {
            if(vis[i]&&use[i])
            {
                del[i]=1;
                int bt2=Kruskal(0);
                if(bt1==bt2)
                {
                    flag=0;
                    break;
                }
                del[i]=0;
            }
        }
        if(flag)printf("%d\n",bt1);
        else printf("Not Unique!\n");
    }
}