洛谷 P4362 [NOI2002]贪吃的九头龙

https://www.luogu.org/problemnew/show/P4362

首先有个很显然的dp:ans[i][j][k]表示i节点用j号头,i节点为根的子树中共有k个点用大头时i节点为根的子树内的最小答案

可以发现复杂度不太对。。

研究一下,可以发现:如果没有大头的限制,且有>=2个头,那么答案一定是0

毕竟,只要把所有节点按深度分类,同一深度的用同一种头,深度相差1的任意两类用不同种头,那么答案就是0了

也可以发现:有了大头的限制,且有>=3个头,那么确定每个节点是否用大头之后,一定可以确定一种方案(即确定所有不是大头的节点具体用哪个头),并保证任意两个不是大头的节点间不产生贡献(只要把所有不是大头的节点按深度分类就行了)

那么,状态简化为:ans[i][j][k]表示i号节点是/否用大头(由k决定),i号节点为根的子树中有j个点用大头时,i号节点为根的子树中的最小答案

可以做了。。如果有>=3个头,照上面的做dp;如果只有2个头,与>=3个头时的区别仅仅是任意两个不是大头的节点间一定产生贡献,稍微改一下就行

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<vector>
 5 using namespace std;
 6 #define fi first
 7 #define se second
 8 #define mp make_pair
 9 #define pb push_back
10 typedef long long ll;
11 typedef unsigned long long ull;
12 typedef pair<int,int> pii;
13 struct E
14 {
15     int to,nxt,d;
16 }e[610];
17 int f1[310],ne;
18 int n,m,K;
19 int an[310][310][2];
20 bool fl1;
21 void dfs(int u,int fa)
22 {
23     int i,j,k,v,t1,t2;
24     an[u][1][1]=an[u][0][0]=0;
25     for(k=f1[u];k;k=e[k].nxt)
26     {
27         v=e[k].to;
28         if(v!=fa)
29         {
30             dfs(v,u);
31             for(i=K;i>=0;i--)
32             {
33                 t1=t2=0x3f3f3f3f;
34                 for(j=0;j<=i;j++)
35                 {
36                     t1=min(t1,min(
37                         an[v][j][0]+an[u][i-j][0]+e[k].d*fl1,
38                         an[v][j][1]+an[u][i-j][0]));
39                     t2=min(t2,min(
40                         an[v][j][0]+an[u][i-j][1],
41                         an[v][j][1]+an[u][i-j][1]+e[k].d));
42                 }
43                 an[u][i][0]=t1;
44                 an[u][i][1]=t2;
45             }
46         }
47     }
48 }
49 int main()
50 {
51     int i,a,b,c;
52     memset(an,1,sizeof(an));
53     scanf("%d%d%d",&n,&m,&K);
54     if(n-K<m-1)
55     {
56         puts("-1");
57         return 0;
58     }
59     for(i=1;i<n;i++)
60     {
61         scanf("%d%d%d",&a,&b,&c);
62         e[++ne].to=b;e[ne].nxt=f1[a];f1[a]=ne;e[ne].d=c;
63         e[++ne].to=a;e[ne].nxt=f1[b];f1[b]=ne;e[ne].d=c;
64     }
65     fl1=(m==2);
66     dfs(1,0);
67     printf("%d",an[1][K][1]);
68     return 0;
69 }

 

posted @ 2018-09-09 18:50  hehe_54321  阅读(220)  评论(0编辑  收藏  举报
AmazingCounters.com