题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2444
题目大意:
给出n个点m条边,问是否可以建立二分图,如果可以的话输出最大匹配。
题解:
利用匈牙利算法计算最大匹配,利用染色法计算是否为2分图
AC代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int V[240][240];
int check[240];
int matching[240];
int n,m;
int col[240];
bool dfs(int u)
{
int i;
for(i = 1; i <= n; i++)
{
if(check[i] || V[u][i] != 1)
continue;
check[i] = 1;
if(matching[i] == -1 || dfs(matching[i]))
{
matching[i] = u;
return true;
}
}
return false;
}
int solve(int n_left)
{
int i, ans = 0;
memset(matching, -1 ,sizeof(matching));
for(i = 1; i <= n_left; i++)
{
memset(check, 0 ,sizeof(check));
if(dfs(i))
ans++;
}
return ans;
}
bool bfs(int s, int n)
{
queue<int> p;
p.push(s);
col[s] = 1;
while(!p.empty())
{
int from = p.front();
p.pop();
for(int i = 1; i <= n; i++)
{
if(V[from][i] && col[i] == -1)
{
p.push(i);
col[i] = !col[from];//染成不同的颜色
}
if(V[from][i] && col[from] == col[i])//颜色有相同,则不是二分图
return false;
}
}
return true;
}
int main()
{
while(cin >> n >> m)
{
memset(col, -1 ,sizeof(col));
memset(V,0,sizeof(V));
bool flag = false ;
while(m--)
{
int a,b;
cin >> a >> b;
V[a][b] = 1;
V[b][a] = 1;
}
for(int i = 1; i <= n; i++)
if(col[i] == -1 && !bfs(i, n))
{//遍历各个连通分支
flag = true;
break;
}
if(!flag)
cout << solve(n)/2 <<endl;
else
cout << "No" <<endl;
}
return 0;
}