首页 > 其他分享 >二分图

二分图

时间:2022-10-22 21:34:10浏览次数:62  
标签:二分 int color edge cs define

判定

  • 一张图是二分图,当且仅当图中不存在奇环。
  • 如果两个集合中的点分别染成黑色和白色,可以发现二分图中的每一条边都一定是连接一个黑色点和一个白色点。

例题:关押罪犯

#include<queue>
#include<cstdio>
#include<iostream>
#include<algorithm>
#define cs const
#define mid (l+r>>1)
#define il inline
#define ri register
#define pc(i) putchar(i)
using namespace std;
cs int N=2e4+3,M=1e5+3,inf=0x3f3f3f3f;
int head[N],n,m,tot,l=1,r,color[N];
struct node{int to,nxt,w;}edge[M<<1];
il void read(int &as)
{
	int f=1;char ch=getchar();as=0;
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') as=(as<<3)+(as<<1)+(ch^48),ch=getchar();as*=f;
}
il void wt(int x){if(x<0) x=-x,pc('-');if(x>9) wt(x/10);pc(x%10|48);}
il void add(cs int u,cs int v,cs int w){edge[++tot]=(node){v,head[u],w},head[u]=tot;}
il bool bfs(cs int x)//验证是否可以构成二分图
{
	queue<int>q;
	for(ri int i(1);i<=n;++i) color[i]=0;
	for(ri int o(1);o<=n;++o)
	{
		if(color[o]) continue;
		q.push(o),color[o]=1;
		while(!q.empty())
		{
			int u=q.front();q.pop();
			for(ri int i(head[u]);i;i=edge[i].nxt)
				if(edge[i].w>=x)
					if(!color[edge[i].to]) 
						q.push(edge[i].to),color[edge[i].to]=-color[u];
					else if(color[edge[i].to]==color[u]) return false;
		}
	}
	return true;
}
int main()
{
	read(n),read(m);
	if(m==1) return puts("0"),0;//特判只有一个人的情况,此时没有怨气值
	for(ri int i(1),u,v,w;i<=m;++i)
		read(u),read(v),read(w),r=r>w?r:w,add(u,v,w),add(v,u,w);
	r++;
	while(r>l+1)//二分答案
		if(bfs(mid)) r=mid; else l=mid;
	wt(l);
	return 0;
}

  

标签:二分,int,color,edge,cs,define
From: https://www.cnblogs.com/zxyc/p/16817373.html

相关文章