题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4616
这道题目数据可能比较弱,搜索都可以AC,但是不敢写,哎……
搜索AC代码:
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <cstdlib> #include <cmath> #include <vector> #include <list> #include <deque> #include <queue> #include <iterator> #include <stack> #include <map> #include <set> #include <algorithm> #include <cctype> #include <ctime> #pragma comment(linker, "/STACK:16777216") using namespace std; typedef __int64 LL; const int N=50005; const int M=55555555; const int INF=0x3f3f3f3f; const double PI=acos(-1.0); vector<int>q[N]; int xh[N],w[N]; int n,c,sm; bool vis[N]; struct love { int i,sum; int cc; }r,e,my[M]; void BFS(int s) { memset(vis,0,sizeof(vis)); vis[s]=1; vector<int>::iterator it; r.i=s; r.sum=xh[s]; sm=max(sm,r.sum); r.cc=c-w[s]; if(r.cc==0) return ; int he=0,ta=0; my[ta++]=r; while(he!=ta) { e=my[he++]; if(he==M) he=0; for(it=q[e.i].begin();it!=q[e.i].end();it++) { r=e; int k=*it; if(vis[k]) continue; vis[k]=1; r.i=k; r.sum+=xh[k]; sm=max(sm,r.sum); r.cc-=w[k]; if(r.cc>0) { my[ta++]=r; if(ta==M) ta=0; } } } } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&c); for(int i=0;i<n;i++) { scanf("%d%d",&xh[i],&w[i]); } for(int i=0;i<=n;i++) q[i].clear(); for(int i=0;i<n-1;i++) { int a,b; scanf("%d%d",&a,&b); q[a].push_back(b); q[b].push_back(a); } int Max=-1; for(int i=0;i<n;i++) { sm=0; if(q[i].size()==1) BFS(i); if(Max<sm) Max=sm; } cout<<Max<<endl; } return 0; }
树形DP代码:
#include <iostream> #include <cstdio> #include <vector> #include <cstring> using namespace std; #define N 50500 int trap[N],val[N],n,C,vis[N],ans; int dp[N][5][2]; vector<int>vec[N]; void DP(int u) { vis[u]=1; dp[u][trap[u]][0]=dp[u][trap[u]][1]=val[u]; int v; for(int i=0;i<vec[u].size();++i) { v=vec[u][i]; if(vis[v]) continue; DP(v); for(int j=0;j<=C;++j) for(int k=0;j+k<=C;++k) { if(j!=C) // j=C的时候已经停止了,不会再往子节点跑了 ans=max(ans,dp[u][j][0]+dp[v][k][1]); if(k!=C) // 同理 ans=max(ans,dp[u][j][1]+dp[v][k][0]); if(j+k<C) // 0表示从子树方向往根节点跑,子树可能是非陷阱的点, //假如j+k==C,题意要求到达C要停止,但按dp[v][k][0]记录的,还会继续跑,所以不行 ans=max(ans,dp[u][j][0]+dp[v][k][0]); //if(j+k<C) //ans=max(ans,dp[u][j][1]+dp[v][k][1]); } for(int j=0;j+trap[u]<=C;++j) dp[u][j+trap[u]][0]=max(dp[u][j+trap[u]][0],dp[v][j][0]+val[u]); for(int j=1;j+trap[u]<=C;++j) // 1表示从根节点往下走的,1->0是不可取的,因为算上1后,已经满C了,就不会再走了,所以不能更新 dp[u][j+trap[u]][1]=max(dp[u][j+trap[u]][1],dp[v][j][1]+val[u]); } } int main () { int ncase;scanf("%d",&ncase); while(ncase--) { scanf("%d%d",&n,&C); for(int i=0;i<n;++i) vec[i].clear(); memset(vis,0,sizeof(vis)); memset(dp,0,sizeof(dp)); ans=0; for(int i=0;i<n;++i) scanf("%d%d",&val[i],&trap[i]); int u,v; for(int i=1;i<n;++i) { scanf("%d%d",&u,&v); vec[u].push_back(v); vec[v].push_back(u); } DP(0); printf("%d\n",ans); } return 0; }