题目:
http://acm.hdu.edu.cn/showproblem.php?pid=2444
题意:
有n个人,其中m对互相认识关系。首先问能不能把n个人分成两组,使每个组内的人互不认识;若可以,按照之前给定的互相认识关系,最多可以分成多少组互相认识的两人组
思路:
判断能不能分成两组,可以用bfs或者dfs染色判断。互相认识两人组的组数可以用匈牙利算法求出
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 210;
struct edge
{
int to, next;
}g[N*N*10];
int cnt, head[N];
int nx, ny, match[N];
int color[N];
bool vis[N];
int a[N*N], b[N*N];
void add_edge(int v, int u)
{
g[cnt].to = u, g[cnt].next = head[v], head[v] = cnt++;
}
bool bfs(int s) //bfs染色,判断可不可以分成满足条件的两组
{
queue<int> que;
que.push(s), color[s] = 1;
while(! que.empty())
{
int v = que.front(); que.pop();
for(int i = head[v]; i != -1; i = g[i].next)
{
int u = g[i].to;
if(color[u] == color[v]) return false;
if(-color[u] == color[v]) continue;
color[u] = -color[v], que.push(u);
}
}
return true;
}
bool dfs(int v)
{
for(int i = head[v]; i != -1; i = g[i].next)
{
int u = g[i].to;
if(! vis[u])
{
vis[u] = true;
if(match[u] == -1 || dfs(match[u]))
{
match[u] = v;
return true;
}
}
}
return false;
}
int hungary(int n)
{
int res = 0;
memset(match, -1, sizeof match);
for(int i = 1; i <= n; i++)
{
if(color[i] == 1)
{
memset(vis, 0, sizeof vis);
if(dfs(i)) res++;
}
}
return res;
}
int main()
{
int n, m;
while(~ scanf("%d%d", &n, &m))
{
cnt = 0;
memset(head, -1, sizeof head);
for(int i = 0; i < m; i++)
{
scanf("%d%d", &a[i], &b[i]);
add_edge(a[i], b[i]), add_edge(b[i], a[i]);
}
bool flag = true;
memset(color, 0, sizeof color);
for(int i = 1; i <= n; i++)
{
if(color[i] == 0) flag = bfs(i);
if(flag == false) break;
}
if(! flag ) printf("No\n");
else printf("%d\n", hungary(n));
}
return 0;
}