题解 | #[NOIP2010]关押罪犯#

[NOIP2010]关押罪犯

https://ac.nowcoder.com/acm/problem/16591

目标:影响力最大的冲突事件最小
常见思路:①贪心;②二分;③搜索、动态规划

贪心:先按照冲突从大到小排序,冲突大的先分开:对每个罪犯建两个点,表示他在A或B监狱。若两人分开,则 罪犯1在A监狱 与 罪犯2在B监狱 合并、1在B与2在A合并。如果后面想分开两人时,发现他们已经在同一集合中,则这个事件就是今年冲突最大的事件

#include <bits/stdc++.h>
using namespace std;
struct point{
    int x,y,nu;
}a[100010];
int comp(struct point p,struct point q){
    return p.nu>q.nu;
}
int fa[20010*2];
int find(int x){
    return (x==fa[x])?x:fa[x]=find(fa[x]);
}
void merge(int x,int y){
    fa[find(x)]=find(y);
}
int main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int n,m;
    cin >> n >> m;
    for(int i=1;i<=2*n;i++){
        fa[i]=i;
    }
    for(int i=0;i<m;i++){
        cin >> a[i].x >> a[i].y >> a[i].nu;
    }
    sort(a,a+m,comp);
    int i=0;
    for(;i<m;i++){
        if(find(a[i].x)!=find(a[i].y) && find(a[i].x+n)!=find(a[i].y+n)){//两人还没合并到同一监狱中
            merge(a[i].x,a[i].y+n);//x在监狱1,y在监狱2合并,这两件事具有相同真假性
            merge(a[i].x+n,a[i].y);//x在监狱2,y在监狱1合并,这两件事具有相同真假性
        }
        else{
            cout << a[i].nu << "\n";
            return 0;
        }
    }
    cout << "0\n" ;
    return 0;
}
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务