LA 4015 Cave,Chengdu 2007.

185 篇文章 0 订阅
116 篇文章 0 订阅

题意:一棵n个结点的有根树,树的边有正整数权,表示两个结点之间的距离。你的任务是回答这样的询问:从根结点处罚,走不超过x单位距离,最多经过多少个结点?同一个结点经过最多算一次。


分析:设dp[x][j][0]表示以x为根的树经过j个点且回来的最小费用,dp[x][j][1]表示不会来的最小费用。


            则有: dp[x][j][0] = min(dp[x][j][0],dp[x][j-k][0]+2*l+dp[u][k][0]);

                        dp[x][j][1] = min(dp[x][j][1],min(dp[x][j-k][0]+l+dp[u][k][1],dp[x][j-k][1]+2*l+dp[u][k][0]));


#include <vector>
#include <cstdio>
#include <utility>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAXN 547483647
using namespace std;
int n,q,x,y,v,num,root,cnt[505],tot[505],dp[505][505][2];
bool jud[505];
typedef pair<int,int> pii;
vector <pii> son[505];
void dfs(int x)
{
	tot[x] = 1;
	for(pii u : son[x]) 
	{
		dfs(u.first);
		tot[x] += tot[u.first];
	}
	for(int j = 2;j <= tot[x];j++) dp[x][j][0] = dp[x][j][1] = MAXN;
	dp[x][1][0] = dp[x][1][1] = dp[x][0][0] = dp[x][0][1] = 0;
	for(int i = cnt[x];i;i--)
	{
		int u = son[x][i-1].first,l = son[x][i-1].second;
		for(int j = tot[x];j;j--)
	  	 for(int k = 1;k <= tot[u] && k <= j;k++)
	 	 {
	 		dp[x][j][0] = min(dp[x][j][0],dp[x][j-k][0]+2*l+dp[u][k][0]);
	 		dp[x][j][1] = min(dp[x][j][1],min(dp[x][j-k][0]+l+dp[u][k][1],dp[x][j-k][1]+2*l+dp[u][k][0]));
	  	 }
	}
}
int main()
{
	cin.sync_with_stdio(false);
	while(cin>>n && n)
	{
		cout<<"Case "<<++num<<":"<<endl;
		for(int i = 1;i <= n;i++) son[i].clear();
		memset(cnt,0,sizeof(cnt));
		memset(tot,0,sizeof(tot));
		memset(jud,0,sizeof(jud));
		for(int i = 1;i < n;i++) 
		{
			cin>>x>>y>>v;
			x++,y++; 
			jud[x] = true;
			son[y].push_back(make_pair(x,v));
			cnt[y]++;
		}
		for(int i = 1;i <= n;i++) 
		 if(!jud[i]) root = i;
		dfs(root);
		cin>>q;
		for(int i = 1;i <= q;i++)
		{
			int x,j = tot[root];
			cin>>x;
			for(;j;j--) if(dp[root][j][1] <= x) break;
			cout<<j<<endl;
		}
	}
 } 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值