1.染色法判断二分图
二分图:如果点集V可以被划分成两个互不相交的点集,并且这个图中的所有边的两个顶点分别属于两个不同的点集,则称该图为二分图。
奇数环:由奇数条边组成的环。
如果一条边的一个顶点属于点集V,那么另一个点必属于点集W。如果存在奇数环,那么就会存在矛盾。
判断:只要没有奇数环,就是二分图 , 或者染色法不矛盾。
#include <iostream>
#include <cstring>
using namespace std;
const int N = 200010 , M = 100010;
int idx , e[N] , ne[N] , h[N];
int 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 ; 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;
}
int main()
{
memset(h , -1 , sizeof h);
int n , m;
cin >> n >> m;
while(m--)
{
int a , b;
cin >> a >> b;
add(a , b) , add(b , a);
}
bool flag = true;
for(int i = 1 ; i <= n ; i++)
{
if(!color[i])
{
if(!dfs(i , 1))
{
flag = false;
break;
}
}
}
if(flag) puts("Yes");
else puts("No");
return 0;
}
2.匈牙利算法
题目:
可以类比成左边是一堆男生,右边是一堆女生。二分图可以看成如果点与点之间有连线,则男生对女生有好感,而匹配成功则可以看成有好感的男女成为情侣,男女。我们的任务是当一名月老,目的是使最多对男女成为情侣!
在存储时,因为我们用男生去匹配女生,因此要从男生指向女生。
最体现匈牙利算法神奇的一步!
#include <iostream>
#include <cstring>
using namespace std;
const int N = 510 , M = 100010;
int idx , h[N] , e[M] , ne[M];
int match[N];//和妹子成为情侣的男生
bool st[N];//一轮中妹子是否被匹配过
//st数组用来防止重复搜索相同的点。当图中有环的时候,不加st数组可能会无限循环下去,就出现段错误了。
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 ; i = ne[i])//遍历男生有好感的女生
{
int j = e[i];
if(!st[j])//在新的一轮中女生未匹配过
{
st[j] = true;
if(!match[j] || find(match[j]))//如果该女生没有对象或者这个女生的男朋友可以重新找一个
{ //
match[j] = x;
return true;
}
}
}
return false;
}
int main()
{
int n1 , n2 , m;
cin >> n1 >> n2 >> m;
memset(h , -1 , sizeof h);
while(m--)
{
int a, b;
cin >> a >> b;
add(a , b);
}
int res = 0;
for(int i = 1 ; i <= n1 ; i++)
{
memset(st , false , sizeof st);
if(find(i)) res++;
}
cout << res << endl;
return 0;
}