一. 染色法判定二分图
(1)染色法判定二分图
题目来源:染色法判定二分图
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1e5 + 10, M = 2e5 + 10; // 无向图, 所以最大边数是2倍
int e[M], ne[M], h[N], idx;
int st[N];
void add(int a, int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx ++;
}
bool dfs(int u, int color)
{
st[u] = color;
for(int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if(!st[j]) //i指向的点j未染色
{
if(!dfs(j, 3 - color)) return false; //1.j未染色&&染色失败
}
else if(st[j] == color) return false; //2.已经染色,但是颜色相同,矛盾
}
return true; //成功染色
}
int main()
{
int n, m;
scanf("%d%d", &n, &m);
memset(h, -1, sizeof h);
while (m --)
{
int a, b;
scanf("%d%d", &a, &b);
add(a, b), add(b,a); //无向图
}
bool flag = true;
for(int i = 1; i <= n; i ++)
{
if(!st[i])//i未染色
{
if(!dfs(i, 1))//i染色失败,产生冲突
{
flag = false;
break;
}
}
}
if(flag) puts("Yes");//成功
else puts("No"); //失败
return 0;
}
二.匈牙利算法
(1)二分图的最大匹配
题目来源:二分图的最大匹配
#include<iostream>
#include<cstring>
using namespace std;
const int N = 510 , M = 100010;
int n1,n2,m;
int h[N],ne[M],e[M],idx;
bool st[N];
int match[N];
void add(int a , int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
int find(int x)
{
//遍历自己喜欢的女孩
for(int i = h[x] ; i != -1 ;i = ne[i])
{
int j = e[i];
if(!st[j]) //如果在这一轮模拟匹配中,这个女孩尚未被预定
{
st[j] = true; //那x就预定这个女孩了
//如果女孩j没有男朋友,或者她原来的男朋友能够预定其它喜欢的女孩。配对成功
if(!match[j]||find(match[j]))
{
match[j] = x;
return true;
}
}
}
//自己中意的全部都被预定了。配对失败。
return false;
}
int main()
{
memset(h,-1,sizeof h);
cin>>n1>>n2>>m;
while(m--)
{
int a,b;
cin>>a>>b;
add(a,b);//注意:有向图,a向b匹配
}
int res = 0;
for(int i = 1; i <= n1 ;i ++)
{
//因为每次模拟匹配的预定情况都是不一样的所以每轮模拟都要初始化
memset(st,false,sizeof st);
if(find(i)) res++;
}
cout<<res<<endl;
}