二分图的相关


简介

judge from name:可以一分为二的图就是二分图
judge from math :一类特殊的图论模型,图中的每个节点分属与两个不同的点集 A,B,每一条边所连的两个节点,必然一个在 集合 A 中,一个在集合B

二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集,并且图中的每条边所关联的两个顶点分别属于这两个不同的顶点集,则称图G为一个二分图

  • 匹配:在图论中,一个「匹配」(matching)是一个边的集合,其中任意两条边都没有公共顶点。(是子图哦!)
  • 最大匹配:具有最多边的匹配
  • 完美匹配:所有的点都在匹配内
  • 增广路:起始点和终点都为未匹配的点的交错轨

一、判断二分图

1.染色法(黑白染色法)

解释:由于二分图的点仅有两个集合,所以定义两个集合中的其中之一为白点集,另一个为黑点集
对图中的所有点dfs,起始点定为黑色,由于二分图的性质,每一边的两点必然颜色不同

vector<int>g[M];
int color[M];// 每个点的颜色集合,-1表示颜色待定,1表示黑色,0表示白色

bool bipartite_judge(int x)   //基于dfs的算法,x表示起始点
 
{
	int v;
	for(int i=0;i<g[x].size();i++)
	{
		v=g[x][i];
		if(color[x]==color[v])return false;  //一条边连接了2个颜色相同的点,证伪
	
		if(color[v]==-1)
		{
			color [v]=!color [x];
			if(!bipartite_judge(v))//回溯出现证伪,全部结束
			return false;
		 } 
	}
	
	return true;//流程走下来,无问题
} 

2.奇环判定法

思路:如果一个图里有环,且环的节点数为>2的奇数,由定义易知不可能实现二分了(其实染色法已经自带奇环判定咯)

二、二分图的最大匹配

  • 介绍:匹配

匹配:在图论中,一个「匹配」(matching)是一个边的集合,其中任意两条边都没有公共顶点。

1.匈牙利算法

效果:寻找最大匹配数(最大匹配的边数)
手段:递归的寻找所有的单点匹配
核心:类似于搜索回溯的思想
实现:

bool vis[M];    判断一个点有被判断出现    (每次对单点匹配的时候都要初始化)
int match[M];   记录二分图一边点的匹配对象   (持久化且不发生改变)

每次对vis数组进行对于单点进行修改所以

bool  find(int x)
{
	for(int i=h[x];~i;i=nxt[i])
	{
		int v=to[i];
		if(vis[v])
		{
			vis[v]=true;
			
			if(match[v]=0 || find(match[v]))   //增广路的寻找!!
			{
				match[v]=x;    
				return true;
			}
		}
	}
	return false;
}

完全的代码贴在这里!!:

#include<bits/stdc++.h>
using namespace std;
const int M=502;
int cnt;
int n1,n2,m,a,b,ans;
int h[M],to[M],nxt[M];
bool vis[M];
int match[M];

void add(int x,int y)
{
	nxt[++cnt]=h[x];
	h[x]=cnt;
	to[cnt]=y;
}


bool  find(int x)
{
	int v;
	for(int i=h[x];~i;i=nxt[i])
	{
		v=to[i];
		if(!vis[v])
		{
			vis[v]=true;
			if(match[v]==0||find(match[v]))
			{
				match[v]=x;
				return true;
			}
		}
	}
	return false;/// 经过一套判断,已经对二分图具有了判断,前期没有return
	 
}


int main()
{
	
	cin>>n1>>n2>>m;
	memset(h,-1,sizeof h);
	for(int i=1;i<=m;i++)
	{
	    scanf("%d%d",&a,&b);
		add(a,b);
	}
	
	for(int i=1;i<=n1;i++)
	{
		memset(vis,0,sizeof vis);
		if(find(i))ans++;
	}
	cout<<ans;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流苏贺风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值