luogu P4362 [NOI2002]贪吃的九头龙

传送门

最后基本靠自己的思路秒了这个题吧

先排除不合法情况

一个K一个M十分恶心

然后结合不合法仔细想一想只有m==2的时候小头才会产生花费

所以问题就变成选择k个点 花费是所有两个端点都选择的边的边权 求最小花费

按照套路先考虑dp[i][j][0]表示以i为根处理完当前子树 选j个点 0/1表示是否选择根

所以就可以转移

注意一棵子树dp的时候滚动数组不要滚错了 实在不行(像我)开一个tmp代替滚动也行

(memcpy真快)

Time cost: 65min

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<queue>
 6 #include<iostream>
 7 #define ms(a,b) memset(a,b,sizeof a)
 8 #define rep(i,a,n) for(int i = a;i <= n;i++)
 9 #define per(i,n,a) for(int i = n;i >= a;i--)
10 #define inf 2147483647
11 using namespace std;
12 typedef long long ll;
13 typedef double D;
14 #define eps 1e-8
15 ll read() {
16     ll as = 0,fu = 1;
17     char c = getchar();
18     while(c < '0' || c > '9') {
19         if(c == '-') fu = -1;
20         c = getchar();
21     }
22     while(c >= '0' && c <= '9') {
23         as = as * 10 + c - '0';
24         c = getchar();
25     }
26     return as * fu;
27 }
28 //head
29 const int N = 305;
30 int n,m,K;
31 int head[N],nxt[N<<1],mo[N<<1],cst[N<<1],cnt;
32 void _add(int x,int y,int w) {
33     mo[++cnt] = y;
34     cst[cnt] = w;
35     nxt[cnt] = head[x];
36     head[x] = cnt;
37 }
38 void add(int x,int y) {
39     int w = read();
40     _add(x,y,w),_add(y,x,w);
41 }
42 
43 int dp[N][N][2];
44 int tmp[N][2];
45 void dfs(int x,int f) {
46     dp[x][0][0] = dp[x][1][1] = 0;
47     for(int i = head[x];i;i = nxt[i]) {
48         int sn = mo[i];
49         if(sn == f) continue;
50         dfs(sn,x);
51         memcpy(tmp,dp[x],sizeof(tmp));
52         ms(dp[x],63);
53         rep(j,0,K) rep(t,0,j) {
54             dp[x][j][0] = min(dp[x][j][0],dp[sn][t][0] + tmp[j-t][0] + (m == 2) * cst[i]);
55             dp[x][j][0] = min(dp[x][j][0],dp[sn][t][1] + tmp[j-t][0]);
56             dp[x][j][1] = min(dp[x][j][1],dp[sn][t][1] + tmp[j-t][1] + cst[i]);
57             dp[x][j][1] = min(dp[x][j][1],dp[sn][t][0] + tmp[j-t][1]);
58         }
59     }
60 }
61 
62 int main() {
63     n = read(),m = read(),K = read();
64     if(n-m-K+1 < 0) {
65         puts("-1");
66         return 0;
67     }
68     rep(i,2,n) add(read(),read());
69     ms(dp,63);
70     dfs(1,1);
71     printf("%d\n",dp[1][K][1]);
72     return 0;
73 }

 

posted @ 2018-11-05 20:26  白怀潇  阅读(170)  评论(0编辑  收藏  举报