二分图
二分图是图论中的一种特殊模型,可理解为将一个图中的所有节点分到两个互不相交的集合里面,图中的所有边的两个端点可以分别在两个节点区间找到,是分别!也就是说边不在集合内部。
关于如何判断一个图是否为二分图最好的办法就是判断图中是否有奇数环(环边数为奇数)
染色法判断二分图
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1e5 + 5;
int e[2*N], ne[2*N], h[N], idx, color[N];
bool vis[N];
void add(int x, int y)
{
e[idx] = x; ne[idx] = h[y]; h[y] = idx++;
}
bool dfs(int x,int col) {
vis[x] = true;
color[x] = col;
for (int i = h[x]; i != -1; i = ne[i])
{
if (!vis[e[i]]) dfs(e[i], 3-col);
else if (col == color[e[i]]) return false;
}
return true;
}
int main()
{
memset(h, -1, sizeof h);
int n, m, u, v;
cin >> n >> m;
for (int i = 0; i < m; i++){
cin >> u >> v;
add(u, v);
add(v, u);
}
int flag = 1;
for (int i = 1; i <= n; i++){
if (!vis[i]) if (dfs(i, 1) == false) {
flag = 0;
break;
}
}
if(flag==1) cout<<"Yes";
else cout<<"No";
return 0;
}
匈牙利算法–分配问题
题目链接–二分图的最大匹配对
采取的分配方式就是当到达一个节点时,该节点查看选中的节点是否已经被分配,没分配配对成功,否则就查询一下选中节点的分配对象能否换一个选择。
#include<iostream>
#include<cstring>
using namespace std;
const int N = 1e5 + 5, M = 505;
int e[N], ne[N], h[M], idx, match[M];
bool vis[M];
void add(int x, int y)//x->y
{
e[idx] = y; ne[idx] = h[x]; h[x] = idx++;
}
bool dfs(int x)
{
for (int i = h[x]; i != -1; i=ne[i]){
if (!vis[e[i]]){
vis[e[i]] = true;//标记该节点是否已经访问过,避免重复访问
if (!match[e[i]] || dfs(match[e[i]])) {
//vis在对看重对象的原先对象的重新分配对象任然可以使用
match[e[i]] = x;//标记匹配对象
return true;
}
}
}
return false;
}
int main()
{
memset(h, -1, sizeof h);
int cnt = 0;
int n1, n2, m, u, v;
cin >> n1 >> n2 >> m;
while (m--){
cin >> u >> v;
add(u, v);
}
for (int i = 1; i <= n1; i++)
{
memset(vis, false, sizeof vis);//每次匹配前更新所有待选对象都未被访问
if (dfs(i)) cnt++;
}
cout << cnt;
return 0;
}