[题解]关押罪犯

原题链

主要算法:并查集

主要思路:

先用结构体将每一对罪犯的怨气值储存,再用怨气值为关键词从大到小排序。现在,为了让事情的影响最小,我们需要让怨气值最大的一对罪犯不在同一个监狱,所以在从大到小的顺序合并的时候是:

merge(a[i].x,a[i].y + n);
merge(a[i].y,a[i].x + n)

那么,如果在一次合并时,我们发现有两个我们将要合并的人已经在另一个集合里了时就可以输出这时的罪犯$i$的怨气值及时结果。因为我们是从怨气值最大的时候往后操作,那么如果我们要将两个罪犯重新拆开重新合并的话,时间的影响值就会增加, 答案就不能保证最优。

源代码

#include <bits/stdc++.h>
using namespace std;
struct node{
    int x,y;
    int w;
}a[100010];
bool cmp(node c,node d){
    return c.w > d.w;
}
int fa[200010];
int get(int x){
    if(fa[x] == x)return x;
    return fa[x] = get(fa[x]);
}
void merge(int x,int y){
    fa[get(x)] = get(y);
    return;
}
int main(){
    int n,m;
    cin>>n>>m;
    for(int i = 1;i <= 2 * n;i++)fa[i] = i;
    for(int i = 1;i <= m;i++){
        cin>>a[i].x>>a[i].y>>a[i].w;
    }
    sort(a + 1,a + m + 1,cmp);
    for(int i = 1;i <= m;i++){
        if(get(a[i].x) == get(a[i].y)){cout<<a[i].w<<endl;exit(0);}
        merge(a[i].x,a[i].y + n); 
        if(get(a[i].y) == get(a[i].x)){cout<<a[i].w<<endl;exit(0);}
        merge(a[i].y,a[i].x + n);
    }
    cout<<0<<endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/czy--blog/p/11741843.html