The Unique MST POJ - 1679 奇妙的次小生成树

题目链接:POJ1679

题目:判断是否有唯一一个最小生成树。

1.在网上看了好多的代码。。。板子上kuangbin大神次小生成树的代码竟然就是个求最小生成树的。。。。并不完整。

他的博客上倒是有完整的  先码住

kuangbin


 求最小生成树时,用数组Max[i][j]来表示MST中i到j最大边权
 求完后,直接枚举所有不在MST中的边,替换掉最大边权的边,更新答案

    #include <iostream>  
    #include <cstdio>  
    #include <cstring>  
    #include <algorithm>  
    #include <cmath>  
    #define inf 0x3f3f3f3f  
    #define ms(x) memset(x, 0, sizeof(x))  
    using namespace std;  
    const int N = 110;  
    bool vis[N];  
    int lowc[N];  
    int pre[N];  
    int Max[N][N];  
    bool used[N][N];  
    int prime(int cost[][N], int n)  //kuangbin的板子
    {  
        int ans = 0;  
        ms(vis);  
        ms(Max);  
        ms(used);  
        vis[0] = true;  
        pre[0] = -1;  
        for(int i=1; i<n; i++)  
        {  
            lowc[i] = cost[0][i];  
            pre[i] = 0;  
        }  
        lowc[0] = 0;  
        for(int i=1; i<n; i++)  
        {  
            int mic = inf;  
            int p = -1;  
            for(int j=0; j<n; j++)  
                if(!vis[j] && mic>lowc[j])  
                {  
                    mic = lowc[j];  
                    p = j;  
                }  
            if(mic == inf ) return -1;  
            ans+=mic;  
            vis[p] = true;  
            used[p][pre[p]]= used[pre[p]][p] = true;  
            for(int j=0; j<n; j++)  
            {  
                if(vis[j]) Max[j][p] = Max[p][j] = max(Max[j][pre[p]], lowc[p]);  
                if(!vis[j] && lowc[j] > cost[p][j])  
                {  
                    lowc[j] = cost[p][j];  
                    pre[j] = p;  
                }  
            }  
        }  
        return ans;  
    }  
    int ans ;  
    int smst(int cost[][N], int n)  //求次小生成树
    {  
        int mi =inf;  
        for(int i=0;i<n;i++)  
        {  
            for(int j=i+1;j<n;j++)  
            {  
                if(cost[i][j]!=inf && !used[i][j])  
                {  
                    mi = min(mi, ans+cost[i][j] - Max[i][j]);  
                }  
            }  
        }  
        if(mi == inf) return -1;  
        return mi;  
    }  
    int cost[N][N];  
    int main()  
    {  
        int T;  
        scanf("%d",&T);  
        while(T--)  
        {  
            int n,m;  
            scanf("%d%d",&n,&m);  
            for(int i=0;i<n;i++)  
            {  
                for(int j=0;j<n;j++)  
                {  
                    if(i==j) cost[i][j] = 0;  
                    else cost[i][j] = inf;  
                }  
            }  
            while(m--)  
            {  
                int x, y, z;  
                scanf("%d%d%d",&x,&y,&z);  
                x--, y--;  
                cost[x][y] = cost[y][x] = z;  
            }  
            ans = prime(cost,n);  
            if(ans == -1)  
            {  
                printf("Not Unique!\n");  
            }  
            else if(ans == smst(cost, n))  
                printf("Not Unique!\n");  
            else printf("%d\n",ans);  
        }  
        return 0;  
    }  

2.

另外这个博客比较易懂

有待整理。。

思路2.1       用prim 时, 如果有两个符合条件且权值相同的边, 则最小生成树不唯一。

2.2   kruskal   先建个最小生成树, 并用个数组记录下边的id。

枚举边,建树时跳过这些边。如果权值一样, 则不唯一

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值