题目:
Input
The first line contains an integer T, indicating the number of testcases.
For each testcase, the first line contains one integer N(2 <= N <= 50000), the number rooms, and another integer C(1 <= C <= 3), the number of chances to be trapped. Each of the next N lines contains two integers, which are the value of gift in the room and whether have trap in this rooom. Rooms are numbered from 0 to N-1. Each of the next N-1 lines contains two integer A and B(0 <= A,B <= N-1), representing that room A and room B is connected.
All gifts' value are bigger than 0.
Output
For each testcase, output the maximum total value of gifts you can get.
Sample Input
2 3 1 23 0 12 0 123 1 0 2 2 1 3 2 23 0 12 0 123 1 0 2 2 1
Sample Output
146 158
题解
大意:给定一颗树··树上节点有不同价值的礼物···有些节点有陷阱··现可以选择从任意一个节点出发按照任意路线走···但不能返回··规定碰到一定数量的陷阱时就会停止走动··问最多可以拿到多少价值总和的礼物?
写了2个多小时发现有处细节错了··就是一旦碰到规定的陷阱数C就必须停止··然而我的dp并没有注意到这一点··导致整个代码方程直接错了···
参照了网上的方法:http://blog.csdn.net/martinue/article/details/51025232
另外这道题还发现了我的一个误区:求一颗树中的最长链的相关问题··如果我们要确定每个节点上的最长链··也就是说如果问到一个节点我们就能答出它的最长链的话,我们需要按照上一篇文章Bob‘s race那样dp··但遇到类似于这道题··如果只是询问最长链而并不需要知道节点与最长链的对应关系时··我们可以按照这道题的方式进行Dp,详见代码·差别很明显
代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #include<cctype> #include<string> #include<cstring> using namespace std; const int N=50005; const int inf=0x3f3f3f3f; int first[N],nxt[N*2],go[N*2],tot,f[N][5][2],val[N],n,T,C,ans; bool jud[N]; inline int R() { char c;int f=0; for(c=getchar();c<'0'||c>'9';c=getchar()); for(;c<='9'&&c>='0';c=getchar()) f=(f<<3)+(f<<1)+c-'0'; return f; } inline void comb(int a,int b) { nxt[++tot]=first[a],first[a]=tot,go[tot]=b; nxt[++tot]=first[b],first[b]=tot,go[tot]=a; } inline void pre() { tot=ans=0; memset(first,0,sizeof(first));memset(f,-inf,sizeof(f)); } inline void dfs(int u,int fa) { f[u][jud[u]][jud[u]]=val[u];ans=max(ans,val[u]); for(int e=first[u];e;e=nxt[e]) { int v=go[e];if(v==fa) continue; dfs(v,u); for(int i=0;i<=C;i++) for(int j=0;j+i<=C;j++) { if(j+i<=C) ans=max(ans,f[u][i][1]+f[v][j][1]); if(j+i<C) ans=max(ans,f[u][i][0]+f[v][j][0]); if(j!=C) ans=max(ans,f[u][i][1]+f[v][j][0]); if(i!=C) ans=max(ans,f[u][i][0]+f[v][j][1]); } for(int i=0;i<C;i++) { f[u][i+jud[u]][0]=max(f[u][i+jud[u]][0],f[v][i][0]+val[u]); f[u][i+jud[u]][1]=max(f[u][i+jud[u]][1],f[v][i][1]+val[u]); } if(!jud[u]) f[u][C][1]=max(f[u][C][1],f[v][C][1]+val[u]); } } int main() { // freopen("a.in","r",stdin); T=R();int a,b; while(T--) { n=R(),C=R();pre(); for(int i=1;i<=n;i++) val[i]=R(),jud[i]=R(); for(int i=1;i<n;i++) a=R(),b=R(),comb(a+1,b+1); dfs(1,0);cout<<ans<<endl; } return 0; }