poj 1679 The Unique MST(次小生成树)

来源:互联网 发布:pubwin2015数据库账号 编辑:程序博客网 时间:2024/05/20 07:49

判断最下生成树是否唯一的思路:

1、对图中的每一条边,扫描其他边,如果存在相同权值的边,则对该边做标记。

2、然后用Kruskal算法或Prim算法求MST。

3、求得MST后,如果该MST中未包含做了标记的边,即可判断MST唯一;如果包含做了标记的边,则依次去掉这些边再求MST,如果求得的MST权值和原来的MST的权值一样,即可判断MST不唯一。

针对poj 1679这题,采用Kruskal算法求MST,并判断MST是否唯一:

#include<iostream>#include<cstdio>#include<algorithm>const int N=110;using namespace std;struct Edge{    int u,v,w;  //边的顶点、权值    bool operator < (const Edge &p) const {        return w<p.w;    }    int equal; //标记,1表示存在权值相同的边,0表示不存在    int used;//在第一次求得的MST中,是否包含该边    int del;  //1删除,0未删除}edge[N*N];int n,m;bool first;int parent[N];//初始化void UFset(){    for(int i=0;i<n;i++){        parent[i]=-1;    }}int Find(int x){    int s;    for(s=x;parent[s]>=0;s=parent[s]);    //压缩路径,优化    while(s!=x){        int temp=parent[x];        parent[x]=s;        x=temp;    }    return s;}//合并void Union(int R1,int R2){    int r1=Find(R1);    int r2=Find(R2);    int temp=parent[r1]+parent[r2];    if(parent[r1]>parent[r2]){        parent[r1]=r2;        parent[r2]=temp;    }else {        parent[r1]=temp;        parent[r2]=r1;    }}int kruskal(){    int sumweight=0,num=0;    int u,v;    UFset();    for(int i=0;i<m;i++){        if(edge[i].del==1)continue;//忽略去掉的边        u=edge[i].u,v=edge[i].v;        if(Find(u)!=Find(v)){            sumweight+=edge[i].w;            num++;            Union(u,v);            if(first)edge[i].used=1;        }        if(num>=n-1)break;    }    return sumweight;}int main(){    int u,v,w,t;    scanf("%d",&t);    while(t--){        scanf("%d%d",&n,&m);        for(int i=0;i<m;i++){            scanf("%d%d%d",&u,&v,&w);            edge[i].u=u-1,edge[i].v=v-1,edge[i].w=w;            edge[i].equal=0,edge[i].used=0,edge[i].del=0;        }        // 标记权值相同的边        for(int i=0;i<m;i++){            for(int j=0;j<m;j++){                if(i==j)continue;                if(edge[j].w==edge[i].w){                    edge[i].equal=1;                }            }        }        sort(edge,edge+m);        first=true;        int weight1=kruskal(),weight2;//第一次求MST        first=false;        int tag=1;        for(int i=0;i<m;i++){            if(edge[i].used&&edge[i].equal){                edge[i].del=1;                weight2=kruskal();                if(weight1==weight2){                    printf("Not Unique!\n");                    tag=0;                    break;                }                edge[i].del=0;            }        }        if(tag)            printf("%d\n",weight1);    }    return 0;}


0 0
原创粉丝点击