转载请注明出处,谢谢:http://www.cnblogs.com/KirisameMarisa/p/4374766.html ---by 墨染之樱花
【题目链接】http://poj.org/problem?id=2486
【题目描述】给一张顶点带权值的图,求从1号点出发走k步的最大总权值(顶点可以重复走)
【思路】经典的树形dp,本沙茶看了别人的题解才会orz。。。。详情请见下面的代码中的详细注释
/* *********************************************** Author :Kirisame_Marisa blog :http://www.cnblogs.com/KirisameMarisa/ Created Time :2015年03月28日 星期六 18时56分45秒 File Name :c.cpp ************************************************ */ #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> using namespace std; const int INF=0x3f3f3f3f; const int MAXN=1000; #define eps 1e-10 #define zero(x) (fabs(x)<eps) #define REP(X,N) for(int X=0;X<N;X++) #define REP2(X,L,R) for(int X=L;X<=R;X++) #define CLR(A,X) memset(A,X,sizeof(A)) #define PB(X) push_back(X) #define MP(X,Y) make_pair(X,Y) #define IT iterator #define test puts("OK") typedef long long ll; typedef pair<int,int> PII; typedef vector<int> VI; typedef vector<PII> VII; int a[110]; VI G[110]; int V,k; int dp[110][210][2]; //dp[i][j][t]在i为根的子树中走k步,t=0表示不回到根,t=1表示回到根 void dfs(int u,int par) { REP(i,G[u].size()) { int v=G[u][i]; if(v==par) continue; dfs(v,u); for(int j=k;j>=1;j--) { //回到u只有一种情况:先后在v根子树中走p步,其他子树中走j-p-2步 REP2(p,0,j-2) //p表示在以v为根的子树中走p步,由于uv两点来回要两步,所以范围显然是0到j-2,下同 if(dp[u][j-p-2][1]+dp[v][p][1]>dp[u][j][1]) dp[u][j][1]=dp[u][j-p-2][1]+dp[v][p][1]; //不回到u有两种情况:1.u到v,在v子树中转一圈回到v,再回到u,最后走其他子树不再回来 REP2(p,0,j-2) if(dp[u][j-p-2][0]+dp[v][p][1]>dp[u][j][0]) dp[u][j][0]=dp[u][j-p-2][0]+dp[v][p][1]; //2.走其他子树回到u,再到v,在v子树中不回来(会不会到v都行,因为只要不再回u,不过不考虑这个也能AC -_-b) REP2(p,0,j-1) //由于uv之间只要走一次u到v,所以范围是0到j-1 if(dp[u][j-p-1][1]+max(dp[v][p][0],dp[v][p][1])>dp[u][j][0]) dp[u][j][0]=dp[u][j-p-1][1]+max(dp[v][p][0],dp[v][p][1]); } } } int main() { //freopen("in","r",stdin); //freopen("out","w",stdout); while(~scanf("%d%d",&V,&k)) { REP(i,V) G[i].clear(); REP(i,V) scanf("%d",&a[i]); REP(i,V) REP2(j,0,k) dp[i][j][0]=dp[i][j][1]=a[i]; //初始化 REP(i,V-1) { int x,y; scanf("%d%d",&x,&y); x--;y--; G[x].PB(y); G[y].PB(x); } dfs(0,-1); printf("%d ",max(dp[0][k][0],dp[0][k][1])); } return 0; }