原题链接:​​http://acm.hdu.edu.cn/showproblem.php?pid=2444​


题意:给定n个人的m对关系,判断是否可以组成二分图,不可以的话输出No;不然输出最大匹配数。


#define _CRT_SECURE_NO_DEPRECATE 

#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#define INF 99999999;
using namespace std;

int n, m;
int a[205][205];
int color[205];
int match[205];
int vis[205];

bool bfs(int s)
{
queue<int> Q;
Q.push(s);
color[s] = 1;

while (!Q.empty())
{
int u = Q.front();
Q.pop();
for (int v = 1; v <= n; v++)
{
if (a[u][v] && color[v] == -1)
{
color[v] = 1 - color[u];
Q.push(v);
}
else if (a[u][v] && color[v] == color[u])
return false;
}
}
return true;
}

/* 要从1到n一个一个判断,因为可能图是不连通的,也就是起点就是一个独立点 */
bool judge()
{
memset(color, -1, sizeof(color));
for (int i = 1; i <= n; i++)
if (color[i] == -1 && !bfs(i))
return false;
return true;
}

int dfs(int u)
{
for (int v = 1; v <= n; v++)
{
if (a[u][v] && !vis[v])
{
vis[v] = 1;
if (match[v] == -1 || dfs(match[v]))
{
match[v] = u;
match[u] = v;
return 1;
}
}
}
return 0;
}

int hungarian()
{
int ans = 0;
memset(match, -1, sizeof(match));
for (int i = 1; i <= n; i++)
{
if (match[i] == -1)
{
memset(vis, 0, sizeof(vis));
ans += dfs(i);
}
}
return ans;
}

int main()
{
int x, y;
while (~scanf("%d%d", &n, &m))
{
memset(a, 0, sizeof(a));

for (int i = 1; i <= m; i++)
{
scanf("%d%d", &x, &y);
a[x][y] = a[y][x] = 1;
}

if (!judge())
printf("No\n");
else
printf("%d\n", hungarian());
}
return 0;
}