• 【并查集】【P1525】关押罪犯


    传送门

    Description

    Input

    Output

    Sample Input

    4 6
    1 4 2534
    2 3 3512
    1 2 28351
    1 3 6618
    2 4 1805
    3 4 12884

    Sample Output

    3512

    Hint

    Solution

      非常显然的并查集题目,在本题中,对于每个罪犯i,维护两个信息:必须要和他关在一起的罪犯的集合,以及和他有仇的罪犯的集合,由于监狱只有两个,所以和他有仇的罪犯一定被关在同一个集合里面。sort一遍贪心从上到下扫描。对于不得不管起来的两个有仇的人即为答案。

    Code

    #include<cstdio>
    #include<algorithm>
    namespace read{
        void imop(int&x){
            char ch=getchar();
            while(ch<'0'||ch>'9') ch=getchar();
            while(ch>='0'&&ch<='9')   x=x*10+ch-'0',  ch=getchar();
            return;
        }
        void op(int&x){
            char ch=getchar();
            int f=1;
            while(ch<'0'||ch>'9'){
                if(ch=='-') f=-1;
                ch=getchar();
            }
            while(ch>='0'&&ch<='9')   x=x*10+ch-'0',  ch=getchar();
            x*=f;
            return;
        }
    }
    namespace fusu{
        const int maxn = 20010 , maxm = 100010;
        struct Crim{
            int a,b,value;
        };
        Crim criminal[maxm];
        int n,m;
        inline bool cmp(Crim a,Crim b){return a.value<b.value;}
        int frog[maxn],enemy[maxn];
        inline int find(int x){
            if(frog[x]^x)    frog[x]=find(frog[x]);
            return frog[x];
        }
        void gather(int a,int b){
            int fa=find(frog[a]),fb=find(frog[b]);
            frog[fa]=fb;
            return;
        }
        void beginning(){
            for(int i=1;i<=n;++i)
                frog[i]=i;
            return;
        }
        int doit(){
            read::imop(n);read::imop(m);
            for(int i=1;i<=m;++i){
                read::imop(criminal[i].a);
                read::imop(criminal[i].b);
                read::imop(criminal[i].value);
            }
            std::sort(criminal+1,criminal+1+m,cmp);
            beginning();
            do{
                int fa=find(frog[criminal[m].a]),fb=find(frog[criminal[m].b]);
                if(!(fa^fb)){
                    printf("%d
    ",criminal[m].value);
                    return 0;
                }
                if(!enemy[criminal[m].a])    enemy[criminal[m].a]=criminal[m].b;
                    else gather(enemy[criminal[m].a],criminal[m].b);
                if(!enemy[criminal[m].b])    enemy[criminal[m].b]=criminal[m].a;
                    else gather(enemy[criminal[m].b],criminal[m].a);
                --m;
            }while(m);
            printf("0
    ");
            return 0;
        }
    }
    int main(){
        return fusu::doit();
    }

    Summary

    对于并查集中的补集法,对于每个个体记录多个信息,在合并时合并多个信息即可。

  • 相关阅读:
    swift5.x for-in, switch语句
    swift5.x 数组(Array)的基本操作
    OC NSDictionary的属性一般为什么要设置为copy
    iOS APP 从编译到运行
    重装win10系统之后,如何使用之前的虚拟机
    [Delphi]接口认识
    [QPlugins]学习大纲
    [QPlugins]概述
    [转发]Oauth 1.0 1.0a 和 2.0 的之间的区别有哪些?
    [Delphi] Webbroker ISAPI 示例说明
  • 原文地址:https://www.cnblogs.com/yifusuyi/p/9201021.html
Copyright © 2020-2023  润新知