[luogu1525] 关押罪犯{二分图判定}

版权声明:~~~感谢支持! https://blog.csdn.net/qq_39897867/article/details/89260709

题目

https://www.luogu.org/problemnew/show/P1525


解题思路

首先,我们考虑这样一个判定问题:是否存在一种分配方案,使得最小的矛盾值不超过mid。显然,当mid较小时可行的方案对于mid较大时依然可行。换言之,本题的答案具有单调性,可以采用二分的方法求解,将求最小值问题转换为判定问题

策略如下:我们二分答案,设当前二分的值为mid,此时任意两个矛盾双方x和y必须被分在两个不同集合中,将罪犯们作为节点,在矛盾值大于等于mid的罪犯之间连一条边,我们得到一张无向图。此时我们只需判定这张无向图是否为二分图即可(因为要分为两部分),如果是二分图,令二分右端点R=mid,否则令L=mid即可


代码

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std; 
struct node{int y,z,next;}a[200005];
int n,m,head[200005],tot,l,r,c[20005]; 
void add(int x,int y,int z){a[++tot]=(node){y,z,head[x]};head[x]=tot;}
bool binary_picture(int k){
	queue<int> q; memset(c,0,sizeof(c)); 
	for (int i=1;i<=n;i++) if (!c[i]){
		q.push(i); c[i]=1; 
		while (!q.empty()){
			int x=q.front(); q.pop(); 
			for (int j=head[x];j;j=a[j].next)if(a[j].z>=k){
				if (!c[a[j].y]){
					if (c[x]==1) c[a[j].y]=2; else c[a[j].y]=1; q.push(a[j].y); 
				} else if (c[a[j].y]==c[x]) return false; 
			}	
		}
	}
	return true; 
}
int main(){
	scanf("%d%d",&n,&m); int x,y,z; 
	for (int i=1;i<=m;i++){scanf("%d%d%d",&x,&y,&z); r=max(r,z); add(x,y,z); add(y,x,z);} r++;  
	while (l+1<r) {
		int mid=(l+r)>>1; 
		if (binary_picture(mid)) r=mid; else l=mid; 
	}
	printf("%d",l); 
}

猜你喜欢

转载自blog.csdn.net/qq_39897867/article/details/89260709
今日推荐