Link
Solve
此题有并查集和二分图两种做法,我采用的是二分图
本题的答案具有单调性,可以通过二分法,把求最值问题转化成判断问题。
二分答案,设当前二分的值为\(mid\),此时在两个仇恨成都大于\(mid\)的罪犯都必须被安排在不同的*,所以在两个罪犯之间连一条边,得到一张无向图,然后判断这个无向图是否能组成二分图,若是二分图则上界\(r=mid\),否则令下界\(l=mid+1\)
Code
#include<bits/stdc++.h>
using namespace std;
const int maxn=100005,maxe=200005;
int N,M,flg,lnk[maxn],nxt[maxe],son[maxe],w[maxe],cnt,vis[maxn],max_x,ans;
inline int read(){
int ret=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
inline void add_e(int x,int y,int z){son[++cnt]=y;w[cnt]=z;nxt[cnt]=lnk[x];lnk[x]=cnt;}
int DFS(int x,int color,int up){
vis[x]=color;
for(int j=lnk[x];j;j=nxt[j]){
if(w[j]<=up)continue;
if(!vis[son[j]]){
if(!DFS(son[j],3-color,up))return 0;;
}
else if(vis[son[j]]==color)return 0;
}
return 1;
}
int main(){
freopen("P1525.in","r",stdin);
freopen("P1525.out","w",stdout);
N=read();M=read();
for(int i=1;i<=M;i++){
int x=read(),y=read(),z=read();
max_x=max(max_x,z);
add_e(x,y,z);add_e(y,x,z);
}
int L=0,R=max_x,mid;
while(L<=R){
mid=(R-L>>1)+L;flg=0;
memset(vis,0,sizeof vis);
for(int i=1;i<=N;i++){
if(!vis[i])if(!DFS(i,1,mid)){flg=1;break;}
}
if(flg)L=mid+1;
else {R=mid-1;ans=mid;};
}
printf("%d\n",ans);
return 0;
}