之前写过带权并查集解法。
这次是二分图:
二分冲突值。
check时:
把所有冲突值大于mid的每对囚犯连接,即连边。
判断这个的每个联通块能否构成二分图。
能就可以分到2个监狱里。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pb push_back
const int M = 1e5+7;
const int N =2e4+7;
vector<int>G[N];
int n,m;
struct node{
int c,u,v;
}p[M];
int col[N];
bool f;
void dfs(int x,int tp)
{
if(!f)return ;
col[x]=tp;
for(auto y:G[x])
{
if(!col[y])dfs(y,3-tp);
else if(col[y]==col[x])f=false;
}
}
bool ck(int x)//能否满足 冲突值小于等于x
{
for(int i=1;i<=n;i++)G[i].clear();
for(int i=1;i<=m;i++)if(p[i].c>x)G[p[i].u].pb(p[i].v),G[p[i].v].pb(p[i].u);
memset(col,0,sizeof(col));
f=true;
for(int i=1;i<=n;i++)
{
if(col[i])continue;
dfs(i,1);
if(!f)return false;
}
return true;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++)
cin>>p[i].u>>p[i].v>>p[i].c;
int l=0,r=1e9+7,ans=0;
while(l<=r)
{
int m=(l+r)/2;
if(ck(m))ans=m,r=m-1;
else l=m+1;
}
cout<<ans<<endl;
return 0;
}