小游戏

某人很喜欢玩计算机游戏,特别是战略游戏,但是有时他不能尽快找到解所以常常感到很沮丧。现在面临如下问题:他必须在一个中世纪的城堡里设防,城堡里的道路形成一棵无向树。要在结点上安排最少的士兵使得他们可以看到所有边。你能帮助他吗?

你的任务是给出士兵的最少数目。

输入包含多组数据。每组数据表示一棵树,在每组数据中:

第一行是结点的数目。

接下来的几行,每行按如下格式描述一个结点:

结点标识符 : ( 道路的数目 ) 结点标识符1  结点标识符2  ......  结点标识符道路的数目

或者

结点标识符 : (0)

对于 n (0<n<=1500) 个结点,结点标识符是一个从 0 到 n - 1 的整数。每条边在测试用例中只出现一次。

对于每组数据,各给出一个整数表示士兵的最少数目.

 测试输入期待的输出时间限制内存限制额外进程
测试用例 1以文本方式显示
  1. 4↵
  2. 0:(1) 1↵
  3. 1:(2) 2 3↵
  4. 2:(0)↵
  5. 3:(0)↵
  6. 5↵
  7. 3:(3) 1 4 2↵
  8. 1:(1) 0↵
  9. 2:(0)↵
  10. 0:(0)↵
  11. 4:(0)↵
以文本方式显示
  1. 1↵
  2. 2↵
1秒64M0
#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;
}

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值