题目链接:##
题目大意:##
Bob非常享受玩电脑游戏的过程,尤其是策略游戏,但是在有些时候,他因为不能在第一时间找到最佳的策略而十分伤心。 现在,他遇到了一个问题。他必须保卫一个中世纪的城市,有很多道路将整个城市连起来,整体上看上去像一棵树。Bob需要放置尽可能少的士兵,保卫树上所有的边。士兵只能放在节点上,但是却可以保卫所有与这个节点相邻的边。
题目分析:##
由于树本身具有二分图的性质,所以这里我把树手动染色转成二分图,然后跑最小点覆盖
(当然也可以树形dp)
代码:##
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N (1500 + 5)
using namespace std;
inline int read(){
int cnt = 0, f = 1; char c;
c = getchar();
while (!isdigit(c)) {
if(c == '-') f = -f;
c = getchar();
}
while (isdigit(c)) {
cnt = cnt * 10 + c - '0';
c = getchar();
}
return cnt * f;
}
int n, nxt[2*N], to[2*N], first[2*N], tot, x, t, y, Float[N], cnt, black, white, ans, match[N];
bool vis[N];
struct node{
int x;int y;
}edge[N];
void add(int x, int y) {
nxt[++tot] = first[x];
first[x] = tot;
to[tot] = y;
}
void Dfs(int u){
for (register int i = first[u]; i; i = nxt[i]) {
int v = to[i];
if(!Float[v]) {
Float[v] = Float[u] + 1;
Dfs(v);
}
}
}
void build_map() {
memset (first, 0, sizeof(first));
memset (nxt, 0, sizeof(nxt));
memset (to, 0, sizeof(to));
tot = 0;
for (register int i = 1; i <= cnt; i++) {
int X = edge[i].x; int Y = edge[i].y;
if (Float[X] % 2 == 1) {
add(X, Y);
if (!vis[X]) {
vis[X] = true;
black++;
}
if (!vis[Y]) {
vis[Y] = true;
white++;
}
} else {
add(Y, X);
if (!vis[X]) {
vis[X] = true;
white++;
}
if (!vis[Y]) {
vis[Y] = true;
black++;
}
}
}
}
int find(int u) {
// cout<<u<<"##"<<endl;
for (register int i = first[u]; i; i = nxt[i]) {
int v = to[i];
// cout<<vis[v]<<" "<<v<<endl;
if (vis[v]) {
continue;
} else {
vis[v] = true;
if (match[v] == -1||find(match[v])) {
match[v] = u;
return 1;
}
}
}
return 0;
}
int hungary() {
for (register int i = 1; i <= n; i++) match[i] = -1;
for (register int i = 1; i <= n; i++) {
for (register int j = 1; j <= n; j++) vis[j] = 0;
ans += find(i);
}
return ans;
}
int main(){
while(scanf("%d", &n) != EOF) {
memset(first, 0, sizeof(first));
memset(nxt, 0, sizeof(nxt));
memset(to, 0, sizeof(to));
memset(Float, 0, sizeof(Float));
memset(vis, 0, sizeof(vis));
tot=0; cnt=0; ans=0;
for (register int i = 1; i <= n; i++) {
x = read();
t = read();
for (register int j = 1; j <= t; j++) {
y = read();
edge[++cnt].x = x+1;
edge[cnt].y = y+1;
add(x+1,y+1);
add(y+1,x+1);
}
}
Float[1] = 1;
Dfs(1);
build_map();
// cout<<black<<" "<<white<<endl;
// for(register int i = 1; i <= n; i++) cout<<Float[i];
int res = hungary();
printf("%d
", res);
}
return 0;
}