某人很喜欢玩计算机游戏,特别是战略游戏,但是有时他不能尽快找到解所以常常感到很沮丧。现在面临如下问题:他必须在一个中世纪的城堡里设防,城堡里的道路形成一棵无向树。要在结点上安排最少的士兵使得他们可以看到所有边。你能帮助他吗?
你的任务是给出士兵的最少数目。
输入包含多组数据。每组数据表示一棵树,在每组数据中:
第一行是结点的数目。
接下来的几行,每行按如下格式描述一个结点:
结点标识符 : ( 道路的数目 ) 结点标识符1 结点标识符2 ...... 结点标识符道路的数目
或者
结点标识符 : (0)
对于 n (0<n<=1500) 个结点,结点标识符是一个从 0 到 n - 1 的整数。每条边在测试用例中只出现一次。
对于每组数据,各给出一个整数表示士兵的最少数目.
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 | |
---|---|---|---|---|---|
测试用例 1 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dp[1505][2],v[1505];
int lk[1505][1505];
int n;
//dp第一个值为当前结点自己为士兵的总士兵数。
//dp第二个值为当前结点自己不为士兵,有子结点为士兵的总士兵数。
//经由dfs,由叶子结点向根结点逐层更新dp。
void dfs(int x)
{
v[x]=1;
for(int i=0; lk[x][i]!=-1 ; ++i)
{
int m=lk[x][i];
if(!v[m])
{
dfs(m);
dp[x][1]+=dp[m][0];
dp[x][0]+=min(dp[m][0],dp[m][1]);
}
}
dp[x][0]++;
}
int main(){
while(scanf("%d",&n)!=EOF)
{
memset(dp,0,sizeof(dp));
memset(v,0,sizeof(v));
memset(lk,0,sizeof(lk));
int s,t,k,r;
for(int i=0;i<n;i++)
{
scanf("%d:(%d)",&s,&t);
if(!i) r=s;
int nu=0;
for(int j=0;j<t;++j)
{
cin>>k;
lk[s][nu]=k; //k与s相连
nu++;
}
lk[s][nu]=-1;
}
dfs(r);
cout<<min(dp[r][0],dp[r][1])<<endl;
}
return 0;
}