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;
}