[POJ1463] Strategic game

题目链接:##

传送门

题目大意:##

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\n", res);
	}
	
	return 0;
}
posted @ 2019-03-16 10:12  kma_093  阅读(183)  评论(0编辑  收藏  举报