思路

M 对互相仇恨的罪犯,我们按仇恨值从大到小排序,对于每一对互相仇恨的罪犯,我们要设法将他们分配在不同的监狱里,反正不能在同一监狱里

如果不可避免的在同一监狱了 也就是与我们的策略发生冲突了,那么此时的仇恨值就是答案
如果到最后都不曾发生冲突,那么答案是 0,因为此时:任意一对会冲突的罪犯 都不会位于同一个监狱(二分图)

不管是 从大到小排序 还是 分配在不同的监狱里,这一切都是为了保证:矛盾的最大值最小(题意要求)

法1:种类并查集:开二倍空间

令 x 表示 x 自身,x + n 表示 x 的敌人

Code

#include <bits/stdc++.h>

using namespace std;

const int N = 20010,M = 100010;

struct node{
    int a,b;
    int w;
    bool operator < (const node & x) const { return w > x.w ;}
}p[M]; 
int fa[N*2];
int n,m;

int find(int x){
    if(x==fa[x]) return x;
    return fa[x]=find(fa[x]);
}

int main(){
    cin>>n>>m;
    for(int i=0;i<m;i++) {
        int a,b,w;
        cin>>a>>b>>w;
        p[i]={a,b,w};
    }
    sort(p,p+m);
    for(int i=1;i<=2*n;i++) fa[i]=i;  // x表示本身,x+n表示x的敌人

   for(int i=0;i<m;i++){
       int a=p[i].a,b=p[i].b,w=p[i].w;
       if(find(a)==find(b)){  //a和b敌对,不应该在同一集合
           cout<<w<<endl;
           return 0;
       }
       else{  // 因为a、b敌对,所以a和b不应在同一集合,又b与其敌人不在同一集合
             // 所以a和b的敌人放一起
            // 同理:b和a的敌人放一起
            fa[find(a)]=find(b+n);
            fa[find(b)]=find(a+n);
       }
   }
    cout<<0<<endl;

    return 0;
}

法2:思想一样,但做法不同

因为只有两个集合,所以可以开辟数组 Enemy[i] = i, i 的敌人是 j
i 的敌人可能有很多,比如 j,k,z 等等,但是我们只需要记录一次就行,也是记录第一个枚举到的敌人就行

举例如下:1,2 敌对,1,3 敌对,1,4 敌对  (已经按权值排好序)
枚举到 1,2 时
enemy[1] 还未赋值,令 enemy[1] = 2
enemy[2] 还未赋值,令 enemy[2] = 1 

枚举到 1,3 时
enemy[1] 已有敌人:2,所以把 3 和 2 放到一个集合
enemy[3] 还未赋值,令 enemy[3] = 1

枚举到 1,4 时
enemy[1] 已有敌人:2,所以把 4 和 2 放到一个集合
enemy[4] 还未赋值,令 enemy[4] = 1

到此,2、3、4 在一个集合里,因为只有两个集合 所以 显然 1 在另一个集合里
因为运行到最后 都没有发生冲突,所以本样例的答案是 0,可验证:其与预期结果一致

Code

#include <bits/stdc++.h>

using namespace std;

const int N = 20010,M = 100010;

struct node{
    int a,b;
    int w;
    bool operator < (const node & x) const { return w > x.w ;}
}p[M]; 
int fa[N];
int Enemy[N];
int n,m;

int find(int x){
    if(x==fa[x]) return x;
    return fa[x]=find(fa[x]);
}

int main(){
    cin>>n>>m;
    for(int i=0;i<m;i++) {
        int a,b,w;
        cin>>a>>b>>w;
        p[i]={a,b,w};
    }
    sort(p,p+m);

    for(int i=1;i<=n;i++) fa[i]=i;
    for(int i=0;i<=m;i++){
        int a=p[i].a,b=p[i].b,w=p[i].w;
        if(find(a)==find(b)) {
            cout<<w<<endl;   // 冲突不可避免
            return 0;
        }
        else{  // 设法避免冲突:敌人的敌人是朋友
            if(!Enemy[a]) Enemy[a]=b;
            else fa[find(b)]=find(Enemy[a]);
            if(!Enemy[b]) Enemy[b]=a;
            else fa[find(a)]=find(Enemy[b]);
        }
    }
    cout<<0<<endl;  // 冲突可避免

    return 0;
}