定义:如果一张无向图的N个节点可以分成A,B两个非空集合,其中A∩B=∅,并且在同一个集合内的点之间都没有边相连,那么称这张无想吐为一张二分图。A,B分别称为二分图的左部和右部。图例:
图片来自 二分图_百度百科
定理:一张图是二分图,当且仅当图中不存在奇数环(长度为奇数的环),
证明:如图所示,存在奇数环时不管怎么样都会有一个点会与其中的一个集合内的点有连边。
偶数环形成的二分图:
二分图的判定:染色法
从点1开始,给定颜色1,与1相连的点都设置为颜色2,与颜色2相连的点都设置为颜色1,如此往复。当出现两个相邻的点颜色相同时则出现了矛盾。
在一个图中,只有有环的情况下才有可能出现矛盾,有奇数环的情况下一定会有矛盾。
染色法模板:
bool dfs(int u,int c)
{
coloe[u]=c;
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(!color[j]) //如果当前相连的点未被染色
{
if(!dfs(j,3-c))
return false;
}else if(color[j]==c) //如果当前相连的点的颜色与其相同。
return false;
}
return true;
}
推论:一个图是二分图等价于染色法无矛盾等价于不存在奇数环。
证明:
有奇数环情况下,无论从哪一个点开始都会有两个点颜色相同且相连,此时染色法有矛盾。
二分图的最大匹配
匹配的定义:给定一个二分图(前提),如果其中一个边的集合M里面的所有边都没有公共点,那么就称这个边的集合为二分图的一个匹配。
这个二分图能够得到的拥有最多边的一个匹配就称为二分图的最大匹配。图例:
图中由绿色的边组成的集合就是一组匹配。
求二分图的最大匹配:
匹配边:对于任意一组匹配S,属于S的边被称为"匹配边",不属于S的边被称为非匹配边,匹配边的端点就是匹配点,其他节点被称为非匹配点。(红色存疑?)
增广路径:
如果一个在二分图里面存在一条连接两个非匹配点的路径T使得路径上的匹配边和非匹配边交替出现,则称T是匹配S的增广路径。
翻转:将增广路径中匹配边变成非匹配边,非匹配边变成匹配边。
性质1:增广路径的起点和终点一定是非匹配点。
性质2:路径的上一共有奇数条边。
性质3:因为起点终点都是非匹配点,所以非匹配的边的数量一定比匹配边的数量大1
推论:一个匹配S是最大匹配等价于不存在S的增广路径。
匈牙利算法:
将二分图分为左右两个部分。,设左边的是x,右边的是y。
每一次都从左边开始枚举,给左边的一个点x找到一个点y。
x和y能够匹配上的条件有两个,满足其中一个即可:
1.y本身就是非匹配点,还没有任何点和它匹配上。
2.y已经有一个点x1和它匹配,但是x1可以找到另一个点y1和它匹配,这时就可以在返回时将y1和x1匹配,将y和x匹配。
一个对理解这个算法很有帮助的演示视频:
匈牙利算法求最大匹配模板:
bool find(int u)
{
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(!st[j])
{
st[j]=true;
if(match[j]==0||find(match[j]))
{
match[j]=u;
return true;
}
}
}
return false;
}
//主函数里面
int res=0;
for(int i=1;i<=n1;i++)
{
memset(st,0,sizeof st);
if(find(i)) res++;
}
printf("%d\n",res);