并查集P1525关押罪犯

Posted yifusuyi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并查集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

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

以上是关于并查集P1525关押罪犯的主要内容,如果未能解决你的问题,请参考以下文章

P1525 关押罪犯 并查集

洛谷P1525 关押罪犯 并查集

P1525 关押罪犯 并查集

P1525 关押罪犯(二分图/并查集)

P1525 关押罪犯 - 二分+二分图染色||并查集

P1525 关押罪犯扩展域并查集