题解P1525 关押罪犯

Posted call-me-zhz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解P1525 关押罪犯相关的知识,希望对你有一定的参考价值。

这道题是一道比较好的并查集的题目,蒟蒻顿时感觉我学了一个假的并查集。

思路

首先,这道题的意思是:
给你 \(n\) 个点,将他们任意分成两边,求这些点之前权值最大的边尽量的小,求这个值。

我们如何用并查集来做呢?
首先,我们将所有边从大到小排序,对于每两个点 \(x\)\(y\) ,我们将 \(x\)\(y\) 的敌人放一起, \(x\)的敌人和 \(y\) 放一起,敌人的敌人就是我的朋友。
当两个点不得不连接在一起时,那么我们就输出这条边的边权,特别的,如果没有两个点被迫连在一起,那么就需要输出 \(0\)
为什么这样做是对的呢?
首先,我们的边权是从大到小排的,当第一次出现两个不得不连接在一起的点时,当前这条边的边权肯定是最大的。
那么,对于第 \(i\) 个点的敌人 \(b[i]\) ,它与 \(i\) 的连边肯定是最大的,那么对于 \(x\)\(y\)\(x\) 连上 \(y\) 的敌人肯定要比 \(x\)\(y\) 连边的权值要小,不然的话,我们就会先遍历到这条边,再遍历 \(x\)\(y\) 的这条边。
\(Code:\)

#include <iostream>
#include <cstdio>
#include <algorithm> 
#define N 100011
using namespace std;
struct Node

    int u,v,w;
a[N];
int f[N],b[N];
bool cmp(Node x,Node y)

    return x.w>y.w;

int getf(int v)

    return f[v]==v?v:f[v]=getf(f[v]);

void merge(int x,int y)

    int t1=getf(x),t2=getf(y);
    if(t1!=t2) f[t2]=t1;
    return;

bool check(int x,int y)

    int t1=getf(x),t2=getf(y);
    if(t1==t2) return true;
    else return false;

int main()

//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;++i)
        scanf("%d %d %d",&a[i].u,&a[i].v,&a[i].w); 
    sort(a+1,a+m+1,cmp);
    for(int i=1;i<=n;++i) f[i]=i;
    for(int i=1;i<=m+1;++i)
    
        int x,y;
        x=a[i].u; y=a[i].v;
        int t1=getf(x),t2=getf(y);
        if(check(x,y)) 
        
            printf("%d",a[i].w);
            return 0;
         
        if(!b[x]) 
            b[x]=y;
        else 
            merge(b[x],y);
        if(!b[y]) 
            b[y]=x;
        else 
            merge(b[y],x);
    
    return 0;

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

P1525 关押罪犯 题解

P1525 关押罪犯 题解

题解P1525 关押罪犯

洛谷 P1525 关押罪犯==codevs 1069 关押罪犯[NOIP 2010]

P1525 关押罪犯扩展域并查集

洛谷——P1525 关押罪犯