P1525 关押罪犯 题解 Link Solve Code

P1525 关押罪犯

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
",ans);
	return 0;
}