POJ-1679 The Unique MST (判断最小生成树的唯一性)

<题目链接>

题目大意:

给定一张无向图,判断其最小生成树是否唯一。

解题分析:

对图中每条边,扫描其它边,如果存在相同权值的边,则标记该边;用kruskal求出MST。

如果MST中无标记的边,则该MST唯一;否则,在MST中依次去掉标记的边,再求MST,若求得MST权值和原来的MST 权值相同,则MST不唯一。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int M = 1e4+100;
struct EDGE{
    int u,v,w;
    int eq,used,del;
}edge[M];
int n,m;
int father[M];
bool flag;
bool cmp(EDGE a,EDGE b){
    return a.w<b.w;
}
int find(int x){
    if(father[x]!=x)father[x]=find(father[x]);
    return father[x];
}
int Kruscal(){
    for(int i=0;i<1e4+10;i++)father[i]=i;
    int sum=0,num=0;
    for(int i=0;i<m;i++){
        if(edge[i].del)continue;//如果该边被删除,则跳过
        int u=edge[i].u,v=edge[i].v,w=edge[i].w;
        if(find(u)!=find(v)){
            sum+=w,num++;
            if(flag)edge[i].used=1;//将第一次最小生成树的所有边标记
            father[find(v)]=find(u);
        }
        if(num>=n-1)break;
    }
    return sum;
}
int main(){
    int T;scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        memset(edge,0,sizeof(edge));    //用memset能给edge内的所有变量初始化吗?
        for(int i=0;i<m;i++){
            scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
        }
        for(int i=0;i<m;i++){
            for(int j=0;j<m;j++){
                if(i==j)continue;
                if(edge[i].w==edge[j].w)edge[i].eq=1;//判断是否有和它权值相同的边
            }
        }
        sort(edge,edge+m,cmp);
        flag=true;
        int cnt=Kruscal();
        flag=false;
        bool fp=false;
        for(int i=0;i<m;i++){
            if(edge[i].eq&&edge[i].used){
                edge[i].del=1;//如果这条边在第一次求的最小生成树中,并且还有与这条边权值相同的边,那么就试着删除这条边,再跑一遍最小生成树,看得到的权值总和是否与第一次的最小生成树相同
                int res=Kruscal();
                if(res==cnt){
                    fp=true;
                    printf("Not Unique!
");
                    break;
                }
                edge[i].del=0;
            }
        }
        if(!fp)printf("%d
",cnt);
    }
    return 0;
}

2018-10-01

原文地址:https://www.cnblogs.com/00isok/p/9735898.html