• 判断最小生成树是否为一(krustra)


    题目链接:https://vjudge.net/contest/66965#problem/K

    具体思路:

    首先跑一遍最短路算法,然后将使用到的边标记一下,同时使用一个数组记录每一个权值出现的次数,如果出现过的权值超过一次,那么每一次标记一条标记过的边,再去跑最短路算法,如果去除这条边之后的权值和未未去除的时候的权值相同,那么这个最短生成树就不是唯一的,否则就是唯一的。

    AC代码:

    #include<iostream>
    #include<string>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<stdio.h>
    using namespace std;
    # define maxn 100000+10
    # define inf 0x3f3f3f3f
    # define ll long long
    int n,m,tt;
    int vis[maxn];
    int father[maxn];
    int first;
    struct node
    {
        int num;
        int fr;
        int to;
        int cost;
        int chu;
    } q[maxn];
    bool cmp(node t1,node t2)
    {
        return t1.cost<t2.cost;
    }
    int Find(int t)
    {
        return t==father[t]? t: father[t]=Find(father[t]);
    }
    int krustra(int w)
    {
        for(int i=1; i<=n; i++)
        {
            father[i]=i;
        }
        int sum=0;
        for(int i=1; i<=tt; i++)
        {
            if(q[i].num==w)continue;
            int s1=Find(q[i].fr);
            int s2=Find(q[i].to);
            if(s1!=s2)
            {
                sum+=q[i].cost;
                father[s1]=s2;
                if(first==1){//第一次记录未去掉边的时候的所选的边。
                q[i].chu=1;
                }
            }
        }
        return sum;
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            memset(vis,0,sizeof(vis));
            scanf("%d%d",&n,&m);
            tt=0;
            int t1,t2,t3;
            for(int i=1; i<=m; i++)
            {
                scanf("%d%d%d",&t1,&t2,&t3);
                q[++tt].fr=t1;
                q[tt].to=t2;
                q[tt].cost=t3;
                q[tt].num=i;
                q[tt].chu=0;
                q[++tt].fr=t2;
                q[tt].to=t1;
                q[tt].cost=t3;
                q[tt].num=i;
                vis[t3]++;
                q[tt].chu=0;//
            }
            sort(q+1,q+tt+1,cmp);
            first=1;
            int ans=krustra(0);
            first=0;
            int flag=0;
            for(int i=1; i<=tt; i++)
            {
                if(vis[q[i].cost]>=2&&q[i].chu==1)//如果这条边的权值出现过不止一次并且在最短路中出现过,那么这条边就成为了实验对象。
                {
                    int temp=krustra(q[i].num);
                    if(temp==ans)
                    {
                        flag=1;
                        break;
                    }
                }
            }
            if(flag==1)printf("Not Unique!
    ");
            else printf("%d
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    彻底卸载网易UU网游加速器的方法
    OO之策略模式
    android锁屏和finish()后activity生命周期的变化
    ARTS打卡计划第6周-TIPS-多台服务器免密码登录
    ARTS打卡计划第6周-REVIEW-超越编码的避免项目失败的软技能
    ARTS打卡计划第6周-ALGORITHM
    ARTS打卡计划第5周-SHARE-java构建树形结构
    ARTS打卡计划第5周-TIPS
    ARTS打卡计划第5周-REVIEW-SpringBoot的api版本化实践
    ARTS打卡计划第5周-ALGORITHM
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10262866.html
Copyright © 2020-2023  润新知