4844: Noip2010 关押罪犯

题意:有n名罪犯,有m对关系a,b,c分别代表罪犯a和罪犯b有矛盾值c. 现在将这些囚犯放到2个监狱(集合),问最少的矛盾值会是多少

思路:二分最少的矛盾值mid,如果边权<=mid不影响结果,对于>mid的所有边,看是否能形成一张二分图

#include<bits/stdc++.h>
#define PI acos(-1.0)
#define pb push_back
#define F first
#define S second
using namespace std;
typedef long long ll;
const int N=2e5+4;
const int MOD=1e9+7;
//ll a[N],sum[N],dis[N];
//ll cnt[N];

struct node{
    ll v,w;
};
int n,m;
int color[N];
vector<node> edge[N];

bool bfs(int x,ll mid){
    queue<int> q;
    if(!q.empty())  q.pop();
    q.push(x);
    color[x]=1;
    while(!q.empty()){
        int u=q.front();q.pop();
        for(auto t:edge[u]){
            ll v=t.v,w=t.w;
            if(w<=mid)   continue;
            if(color[v]==0){
                color[v]=(color[u]==1)?-1:1;
                q.push(v);
            }
            else{
                if(color[v]==color[u])  return false;
            }
        }
    }
    return true;
}

bool check(ll mid){
    for(int i=1;i<=n;i++){
        if(color[i]==0){
            bool ok=bfs(i,mid);
            if(!ok) return false;
        }
    }
    return true;
}

int main(void){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);

    cin >>n >>m ;
    for(int i=1;i<=m;i++){
        ll u,v,w;
        cin >>u >>v >> w;
        edge[u].pb({v,w});
        edge[v].pb({u,w});
    }
    ll l=0,r=1e12;
    ll ans=0;
//    cout << "~"<<check(3511) << endl;
    while(l<=r){
        memset(color,0,sizeof color);
        ll mid=l+r >> 1;
        if(check(mid))  ans=mid,r=mid-1;
        else    l=mid+1;
    }
    cout << ans << endl;

    return 0;
}