这是一个树上的背包转移。注意要用dp[i][j][k]表示第i个节点用了j的路程是否回到i节点,k=0表示回到i点,k=1表示不回到i点。那么实际上就是树上的一个背包转移。
#include <set> #include <map> #include <queue> #include <stack> #include <cmath> #include <string> #include <cctype> #include <cstdio> #include <cstdlib> #include <cstring> #include <iomanip> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; const int inf = 0x3fffffff; const int mmax =110; struct node { int en; int next; }E[2*mmax]; int p[mmax],w[mmax],num; int dp[mmax][210][2]; void init() { memset(p,-1,sizeof p); num=0; } void add(int st,int en) { E[num].en=en; E[num].next=p[st]; p[st]=num++; } int n,K; bool vis[mmax]; void dfs(int u) { vis[u]=1; for(int i=p[u];i+1;i=E[i].next) { int v=E[i].en; if(!vis[v]) { dfs(v); for(int j=K;j>=0;j--) { for(int e=0;e<=K;e++) { if(j-e-2>=0 && dp[u][j-e-2][0]+1 && dp[v][e][0]+1) { dp[u][j][0]=max(dp[u][j][0],dp[u][j-e-2][0]+dp[v][e][0]); } if(j-e-1>=0 && dp[u][j-e-1][0]+1) { if(dp[v][e][0]+1) dp[u][j][1]=max(dp[u][j][1],dp[u][j-e-1][0]+dp[v][e][0]); if(dp[v][e][1]+1) dp[u][j][1]=max(dp[u][j][1],dp[u][j-e-1][0]+dp[v][e][1]); } if(j-e-2>=0 && dp[u][j-e-2][1]+1 && dp[v][e][0]+1) { dp[u][j][1]=max(dp[u][j][1],dp[u][j-e-2][1]+dp[v][e][0]); } } } } } } int main() { while(cin>>n>>K) { init(); memset(dp,-1,sizeof dp); for(int i=1;i<=n;i++) { scanf("%d",&w[i]); dp[i][0][0]=dp[i][0][1]=w[i]; } for(int i=1;i<n;i++) { int u,v; scanf("%d %d",&u,&v); add(u,v); add(v,u); } memset(vis,0,sizeof vis); dfs(1); int ans=0; for(int i=0;i<=K;i++) { ans=max(ans,dp[1][i][0]); ans=max(ans,dp[1][i][1]); } printf("%d\n",ans); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-11-09 00:39:53