Problem: 战略游戏

Problem: 战略游戏

Time Limit: 1 Sec Memory Limit: 128 MB
[Submit][Status][Web Board]

Description

Bob喜欢玩电脑游戏,特别是战略游戏。但是他经常无法找到快速玩过游戏的办法。现在他有个问题。他要建立一个古城堡,城堡中的路形成一棵树。他要在这棵树的结点上放置最少数目的士兵,使得这些士兵能了望到所有的路。注意,某个士兵在一个结点上时,与该结点相连的所有边将都可以被了望到。
请你编一程序,给定一树,帮Bob计算出他需要放置最少的士兵。

Input

输入文件中数据表示一棵树,描述如下:
第一行 N,表示树中结点的数目。
第二行至第N+1行,每行描述每个结点信息,依次为:该结点标号i,k(后面有k条边与结点I相连),接下来k个数,分别是每条边的另一个结点标号r1,r2,…,rk。
对于一个n(0 < n <= 1500)个结点的树,结点标号在0到n-1之间,在输入文件中每条边只出现一次。

Output

输出文件仅包含一个数,为所求的最少的士兵数目。

Sample Input

Sample Input1
4
0 1 1
1 2 2 3
2 0
3 0
Sample Input2
5
3 3 1 4 2
1 1 0
2 0
0 0
4 0

Sample Output

Sample Output1
1
Sample Output2
2

HINT

在这里插入图片描述

Code

#include <stdio.h>

int n;
bool g[1501][1501],vis[1501],f[1501],hh[1501]; //f:是否有父节点,hh:是否有子节点

int dfs(int x)
{
	int j=0,k=0,l=0;
	for(int i=0; i<n; i++)
		if(g[x][i])
			if(!hh[i]) j++; //无子节点
			else {
				l+=dfs(i); //l为兵数
				if(!vis[i]) k++; //搜过
			}
	if(j || k) { //若无子节点或搜过
		vis[x]++;
		return l+1;
	} return l;
}

int main(void)
{
	scanf("%d",&n);
	for(int i=1,x,y; i<=n; i++) {
		scanf("%d %d",&x,&y);
		for(int j=1,w; j<=y; j++) {
			scanf("%d",&w);
			f[w]++;
			g[x][w]++;
			hh[x]++;
		}
	}
	int root;
	for(root=0; root<n; root++)
		if(!f[root]) break; //没有父节点则为根
	printf("%d\n",dfs(root));
	return 0;
}
posted @ 2019-05-31 22:32  ZhaoChongyan  阅读(147)  评论(0编辑  收藏  举报