题目:http://www.lightoj.com/volume_showproblem.php?problem=1201
题意:有n个蚊子,这n个蚊子间之间有m个朋友关系,可以看成一个图,保证不会出现环。杀死一只蚊子,它的所有的朋友都会知道,就会有防备而无法被杀死,求最多可以杀死多少只蚊子
思路:就是求图的最大独立集,因为最大独立集中任何两点无关联,在题中就意味着不是朋友,不会有防备。拆点建二分图,求最大匹配,最大独立集 = 顶点数 - 最大匹配
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
struct edge
{
int to, next;
}g[N*N];
int match[N], head[N];
bool used[N];
int nx, ny, cnt, cas = 0;
void add_edge(int v, int u)
{
g[cnt].to = u, g[cnt].next = head[v], head[v] = cnt++;
}
bool dfs(int v)
{
for(int i = head[v]; i != -1; i = g[i].next)
{
int u = g[i].to;
if(! used[u])
{
used[u] = true;
if(match[u] == -1 || dfs(match[u]))
{
match[u] = v;
return true;
}
}
}
return false;
}
int hungary()
{
int res = 0;
memset(match, -1, sizeof match);
for(int i = 1; i <= nx; i++)
{
memset(used, 0, sizeof used);
if(dfs(i)) res++;
}
return res;
}
int main()
{
int t, n, m, a, b;
scanf("%d", &t);
while(t--)
{
cnt = 0;
memset(head, -1, sizeof head);
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i++)
{
scanf("%d%d", &a, &b);
add_edge(a, b);
add_edge(b, a);
}
nx = ny = n;
printf("Case %d: %d\n", ++cas, n - hungary() / 2); //因为是拆点建图,所以除去2
}
return 0;
}