题意
给 N 个点和若干条边。
第一问:判断是不是二分图
第二问:如果是二分图,求最大匹配
思路
第一问用染色法判二分图,第二问套模板
题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=2444
AC代码
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxv = 200 + 10;
int N, M;
int Color[maxv];
bool Bg;
/***************************邻接矩阵二分图匹配模板***************************/
int V;
bool G[maxv][maxv];
int Match[maxv];
bool Vis[maxv];
bool dfs(int u)
{
Vis[u] = true;
for(int i= 1; i<= V; i++)
if(G[u][i])
{
int w = Match[i];
if(w < 0 || !Vis[w] && dfs(w))
{
Match[u] = i;
Match[i] = u;
return true;
}
}
return false;
}
int max_match()
{
int res = 0;
memset(Match, -1, sizeof Match);
for(int i= 1; i<= V; i++)
if(Match[i] < 0)
{
memset(Vis, false, sizeof Vis);
if(dfs(i)) res ++;
}
return res;
}
/***************************邻接矩阵二分图匹配模板***************************/
bool C(int u, int pre)
{
if(Color[u] == 0)
{
Color[u] = pre * -1;
for(int i= 1; i<= N; i++)
if(G[u][i])
if(!C(i, Color[u])) return false;
}
else if(Color[u] != pre * -1) return false;
return true;
}
int main()
{
while(scanf("%d %d", &N, &M) != EOF)
{
V = N;
memset(G, false, sizeof G);
for(int i= 1; i<= M; i++)
{
int x, y;
scanf("%d %d", &x, &y);
G[x][y] = G[y][x] = true;
}
Bg = true;
memset(Color, 0, sizeof Color);
for(int i= 1; i<= N; i++)
{
if(Color[i] == 0) Bg &= C(i, -1);
if(!Bg) break;
}
if(!Bg)
{
printf("No\n");
continue;
}
printf("%d\n", max_match());
}
return 0;
}