【SSL1565】将功补过

41 篇文章 0 订阅
21 篇文章 0 订阅

Description

作为间谍专家的Elvis Han受窃取X星球军事中心的秘密情报,他已经成功进入军事中心。但是很不幸的是,在他还没有找到任务需要情报的时候就被发现,这时他清楚他不可能完成任务了,不过还有机会将功补过,也就是得到一些不如任务情报有价值的其他情报,如果得到的情报的总价值大于等于任务情报价值,他也不会受到惩罚。很幸运的是他已经得到的军事中心的地图,情报都是隐藏在各个道路上的,但是他只有时间遍历一定数量的路(时间宝贵呀!还要逃跑。。)现在你做为他的助手,给你地图和每个道路情报价值,希望你分析出,看他能不能将功补过。
  军事中心是一个严格的二叉树,也就是说,如果有个点可以分道,一定是分出,也只分出2条道路,现在Elvis Han正处在第一个分道处,也就是说树的根结点处。每条道路上都有一个分数,就是这个道路上的情报价值。但是他只有时间走M条路,他的最终情报价值总和就是他所经过的路的情报价值总和(假设他到过的路一定可以把所有情报得到)希望你给出一个方案使得他可以尽量多地获取情报以便将功补过。

Input

共有N行:
第一行:3个数据:N,M,Q(N表示有多少个路口,包括分道和不分道的路口;M表示他可以有时间走的道路总数;Q表示他的任务情报的价值)
第2~N行:每行3个数据,Xi,Yi,Wi (X,Y表示第I条道路连接的2个路口,W表示这条道路上的情报价值分, 注意,所有数据均在Lonint范围内)

Output

共包含2行:
第一行:输出TRUE/FALSE(注意大小写),表示他是否可以收集够任务情报价值
第二行:输出一个数据:
如果他可以完成任务,就输出他收集的情报总价值超过任务情报价值的部分。(正数)
如果不能完成任务,就输出一个数,表示他不能还差多少分才够任务情报价值。(负数)

Sample Input

【样例输入1】

3 1 10
1 2 10
1 3 8

【样例输入2】

9 3 49
6 2 15
7 2 10
8 7 6
7 9 15
1 3 20
2 1 10
4 3 8 
3 5 7

Sample Output

【样例输出1】

TRUE
0

样例说明:(该部分不必输出)
3	 2
(8)\    /(10)
       1   (选择1条路当然选1-2)

【样例输出2】

FALSE
-4
样例说明:
8	9
(6) \  / (15)
     6   7     4         5
(15)\   / (10)\ (8)  /(7)
2            3
          (10)\          /(20)
              1(由于他最大可以取得的是[1->3]+[1->2]+[2->6]3条路径的价值,才45,所以不可能完成任务)

Hint

<数据规模> 
对于30%的数据 保证有N<=10 
对于50%的数据 保证有N<=40 
对于全部的数据 保证有 N<=100 

基本和这道题完全一样,只要加一个判断就行
【SSL1605】&&【Luogu_P2015】二叉苹果树

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
using namespace std;

int n, m, q;
int f[1000][1000], tree[1000][3];
int a[1000][1000], num[1000];

void VL_build(int x);

void VL_gress(int x, int y, int cnt)
{
	num[y]=a[x][y];
	tree[x][cnt]=y;
	a[x][y]=a[y][x]=-1;
	VL_build(y); 
}

void VL_build(int x)
{
	int cnt=0;
	for(int i=0; i<=n; i++)
	{
		if(a[x][i]>=0)
		{
			cnt++;
			VL_gress(x, i, cnt);
			if(cnt==2) return;
		}
	}	
}

void VL_dfs(int x, int k)
{
	if(k==0)f[x][k]==0;
	else if(tree[x][1]==0&&tree[x][2]==0)f[x][k]=num[x];
	else
	{
		f[x][k]=0;
		for(int i=0; i<k; i++)
		{
			if(f[tree[x][1]][i]==0)VL_dfs(tree[x][1], i);
			if(f[tree[x][2]][k-i-1]==0)VL_dfs(tree[x][2], k-i-1);
			f[x][k]=max(f[x][k], f[tree[x][1]][i]+f[tree[x][2]][k-i-1]+num[x]);
		}
	}
}

int main(){
	scanf("%d%d%d", &n, &m, &q);
	for(int i=0; i<=n; i++)
		for(int j=0; j<=n; j++)
			a[i][j]=a[i][j]=-1;
	for(int i=1; i<n; i++)
	{
		int x, y, xy;
		scanf("%d%d%d", &x, &y, &xy);
		a[x][y]=xy;
		a[y][x]=xy;
	}
	VL_build(1);
	VL_dfs(1, m+1);
	if(f[1][m+1]>=q)
		printf("TRUE\n%d", f[1][m+1]-q);
	else
		printf("FALSE\n%d", f[1][m+1]-q);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值