Description
军事中心是一个严格的二叉树,也就是说,如果有个点可以分道,一定是分出,也只分出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
【样例输出2】
FALSE
-4
Hint
<数据规模>
对于30%的数据 保证有N<=10
对于50%的数据 保证有N<=40
对于全部的数据 保证有 N<=100
分析
这题真的跟二叉苹果树一模一样!!
只需要最后加上一个判断答案是否超过任务情报的价值,按题目要求输出即可。
上代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,q,x,y,v,tot,h[101],e[101],f[101][101],s[101][101],p;
struct node
{
int to,next;
}a[220];
void add(int x,int y)
{
a[++tot]=(node){y,h[x]};
h[x]=tot;
}
void dp(int k)
{
e[k]=1;//记录当前节点已经被访问
for(int i=h[k];i>0;i=a[i].next)//,枚举边
{
if(e[a[i].to]==1) continue;//如果它的子节点已经被访问过,那就不用做了。
dp(a[i].to);//递归
for(int j=q;j>0;j--)//两个for类似01背包(选or不选且物品只有一个)
{
for(int g=j-1;g>=0;g--)
{
f[k][j]=max(f[k][j],f[a[i].to][g]+f[k][j-g-1]+s[k][a[i].to]);
// 这句详见博客
}
}
}
}
int main()
{
cin>>n>>q>>p;
for(int i=1;i<=n-1;i++)
{
cin>>x>>y>>v;
add(x,y);
add(y,x);
s[x][y]=s[y][x]=v;//记录权值
}
dp(1);
if(f[1][q]>=p)
{
cout<<"TRUE"<<endl<<f[1][q]-p;
}
else
{
cout<<"FALSE"<<endl<<f[1][q]-p;
}
return 0;
}