vijos p1523 贪吃的九头龙 思考思考再思考,就荒废了4小时

树形DP要有自己的风格,转二叉树是基础,考虑边界最头疼。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 int point[303],next[603],v[603],c[603],cnt=0,N,M,K,f[303][303][2],d[303],con[303],pre[303];
 6 int l[303],r[303];
 7 bool p[303];
 8 void insect(int x,int y,int z){next[cnt]=point[x];point[x]=cnt;v[cnt]=y;c[cnt]=z;cnt++;}
 9 void dfs(int x)
10 {
11     int i,j=-1;
12     for (i=point[x];i!=-1;i=next[i])
13     if (p[v[i]]==0)
14     {
15         p[v[i]]=1;
16         if (l[x]==0) l[x]=v[i],d[v[i]]=c[i],pre[v[i]]=0,j=l[x]; else
17         {
18             r[j]=v[i]; d[v[i]]=c[i]; pre[r[j]]=j; j=r[j];
19         }
20     }
21     if (j==-1) return;
22     dfs(j); con[j]=con[l[j]]+1;
23     while (pre[j]!=0) j=pre[j],dfs(j),con[j]=con[l[j]]+con[r[j]]+1;
24 }
25 int dp(int x,int k,int t)
26 {
27     if (x==0) return 0;
28     if (f[x][k][t]!=-1) return f[x][k][t];
29     int i,l1,r1,num=1000000000;
30     for (i=0;i<k;++i)
31     if ((i<=con[l[x]])&&(k-1-i<=con[r[x]]))
32     {
33         l1=dp(l[x],i,1);
34         r1=dp(r[x],k-1-i,t);
35         num=min(num,l1+r1+(t==1)*d[x]);
36     }
37     for (i=0;i<=k;++i)
38     if ((i<=con[l[x]])&&(k-i<=con[r[x]]))
39     {
40         l1=dp(l[x],i,0);
41         r1=dp(r[x],k-i,t);
42         num=min(num,l1+r1+(M==2)*(t==0)*d[x]);
43     }f[x][k][t]=num;
44     return num;
45 }
46 int main()
47 {
48     memset(point,-1,sizeof(point));
49     memset(next,-1,sizeof(next));
50     memset(f,-1,sizeof(f));
51     memset(v,0,sizeof(v));
52     memset(c,0,sizeof(c));
53     memset(p,0,sizeof(p));
54     scanf("%d %d %d
",&N,&M,&K);
55     if (K+M-1>N) {printf("-1
");return 0;}
56     int i,a,b,c;
57     for (i=1;i<N;++i)
58     {
59         scanf("%d %d %d
",&a,&b,&c);
60         insect(a,b,c);insect(b,a,c);
61     }p[1]=1; dfs(1);
62     printf("%d
",dp(l[1],K-1,1));
63     return 0;
64 }
NOI 2017 Bless All
原文地址:https://www.cnblogs.com/abclzr/p/5095384.html