二分图,染色法判定二分图,匈牙利算法求二分图最大匹配

二分图:将图的顶点划分为两个集合,集合里点之间是没有边连接的。
定理:当且仅当图中不含奇数环图是二分图。

1、860. 染色法判定二分图

思路:将一条边上的两个点染成两种不同的颜色。如果是二分图,由于图中不含奇数环,所以染色过程中一定没有矛盾。

#include
#include
using namespace std;
const int N=1e5+10;
int h[N],e[2*N],ne[2*N],idx;
int n,m,color[N];
void add(int a,int b)
{
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool dfs(int u,int c)
{
	color[u]=c;
	for(int i=h[u];i!=-1;i=ne[i])
	{
		int j=e[i];
		if(!color[j])
		{
			if(!dfs(j,3-c))//3-c很妙,如果该点是染色为1,下一个点就为2,反之,也是
				return false;
		}
		else if(color[j]==c)
			return false;
	}
	
	return true;
}
int main()
{
	memset(h,-1,sizeof(h));
	cin>>n>>m;
	int u,v;
	for(int i=0;i>u>>v;
		add(u,v),add(v,u);
	}
	bool flag=true;
	for(int i=1;i<=n;i++)
	{
		if(!color[i])
		{
			if(!dfs(i,1))//染色失败,不是二分图
			{
				flag=false;
				break;
			}
		}
	}
	if(flag) cout<<"Yes"<

2、匈牙利算法

861. 二分图的最大匹配

匈牙利算法,思想:遍历一边的点,遍历这个点的所有出边,如果出边所对的这个点还没有匹配过,就直接匹配成功,否则查找与这个点匹配的点是否还有其它点可以让它匹配(挖墙脚),有的话让它去匹配其他点,把这个点让给它。

#include
#include
using namespace std;
const int N=510,M=1e5+10;
int h[N],e[M],ne[M],idx;
int match[N];
bool st[N];
int n1,n2,m;
void add(int a,int b)
{
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool find(int x)
{
	for(int i=h[x];i!=-1;i=ne[i])
	{
		int j=e[i];
		if(!st[j])
		{
			st[j]=true;
			if(match[j]==0||find(match[j]))//如果当前的这个点已匹配了,去查找与他匹配的点还有没有其他的点可以匹配的
			{
				match[j]=x;
				return true;
			}
		}
	}
	return false;
}
int main()
{
	memset(h,-1,sizeof(h));
	cin>>n1>>n2>>m;
	int u,v;
	for(int i=0;i>u>>v;
		add(u,v);//虽然无向图,但是由于只需要和另外一部分进行匹配,所以建一边的边就好了
	}
	int res=0;
	for(int i=1;i<=n1;i++)
	{
		memset(st,false,sizeof(st));
		if(find(i)) res++;
	}
	cout<

你可能感兴趣的:(算法,图论,动态规划)