POJ --- 1679 【判断最小生成树是否唯一】

来源:互联网 发布:淘宝卖家信誉等级 编辑:程序博客网 时间:2024/06/05 06:17

网上两种算法对应都有:
题目链接

prim算法判最小生成树是否唯一

下面是这道题的AC代码:

#include<cstdio>#include<cmath>#include<algorithm>#include<iostream>#include<cstring>#define CLR(x) memset(x,0,sizeof(x))using namespace std;const int maxn=105;const int inf=1e9;int cas=1;int n,m;int mapp[maxn][maxn],vis[maxn],dis[maxn];void prim(int u){    CLR(vis);    int flag=0,sum=0;    for(int i=1;i<=n;i++)        dis[i]=mapp[u][i];    vis[u]=1;    for(int i=1;i<=n;i++){        int minn=inf;        int v=-1;        for(int j=1;j<=n;j++){            if(!vis[j] && minn>dis[j]){                v = j;                minn = dis[j];            }        }        if(v!=-1){   //如果v=-1了,说明这个图已经连通了,不用再判断下去了,当然也可以直接break掉,一样的.            //printf("%d %d\n",v,minn);            int ans=0;   //记录相同权值的边有几条,把图画出来就懂的起了!!!            for(int j=1;j<=n;j++){                if(vis[j] && mapp[v][j] == minn)   //这一步处理的非常好.                    ans++;            }            if(ans>1){    //如果大于1,说明用其他路也能达到该点,所以树就不唯一了,所以可以直接break了.                flag=1;                break;            }            sum+=minn;            vis[v]=1;            for(int j=1;j<=n;j++){                if(!vis[j] && dis[j] > mapp[v][j])                    dis[j] = mapp[v][j];            }        }    }    if(flag)        printf("Not Unique!\n");    else        printf("%d\n",sum);}int main(){    int t;    cin >> t;    while(t--){        cin >> n >> m;        for(int i=1;i<=n;i++){            for(int j=1;j<=n;j++){                if(i==j) mapp[i][j]=0;                else mapp[i][j]=inf;            }        }        for(int i=0;i<m;i++){            int u,v,w;            cin >> u >> v >> w;            mapp[u][v] = mapp[v][u] = w;        }        prim(1);   //从点 1 开始找.    }}

kruskal的算法,再用这个算法时有一点要特别注意,否则会一直WA,就是在进行删边操作时,注意删完或需要判断这个图是否是一个树!!!,如果不是的话返回-1或最大值,不要返回sum值,因为删去边后没有树的话,则最小生成树还是唯一的!!!
AC代码:

#include<cstdio>#include<cmath>#include<algorithm>#include<iostream>#include<cstring>#include<set>#include<queue>#include<functional>#include<vector>#include<stack>#include<map>#include<cstdlib>#define CLR(x) memset(x,0,sizeof(x))#define ll long long int#define PI acos(-1.0)#define db double#define mod 1000000007using namespace std;const int maxn = 1e5+5;int pre[105];int n,m;vector<int>used;struct node{ int u,v,w;} s[maxn];void init(){ for(int i=0;i<=n;i++) pre[i]=i; }int Find(int x){ return pre[x]==x?x:pre[x]=Find(pre[x]); }bool cmp(node a,node b){ return a.w<b.w; }int kruskal(int flag){    int num=0;    int sum=0;    for(int i=0;i<m;i++){        if(i==flag) continue;        int u=Find(s[i].u);        int v=Find(s[i].v);        if( u != v){            pre[v]=u;            sum+=s[i].w;            num++;            if(flag==-1)                used.push_back(i);        }        if(num==n-1)            break;    }    int cnt=0;    //一定判断一下树是否联通!!!    for(int i=1;i<=n;i++){        if(pre[i]==i)            cnt++;    }    if(cnt>1)        return -1;    return sum;}int main(){    int t;    scanf("%d",&t);    while(t--){        CLR(s);        scanf("%d %d",&n,&m);        init();        used.clear();     //不要忘了清空!!!        for(int i=0;i<m;i++){            scanf("%d %d %d",&s[i].u,&s[i].v,&s[i].w);        }        sort(s,s+m,cmp);        int ans=kruskal(-1);        int flag=0;        for(int i=0;i<used.size();i++){            init();            int p=0;            p=kruskal(used[i]);            if(p==ans){                flag=1;                break;            }        }        if(flag)            printf("Not Unique!\n");        else            printf("%d\n",ans);    }}
阅读全文
0 0
原创粉丝点击