P1469通向自由的钥匙
|
问题描述
通向自由的钥匙被放n个房间里,这n个房间由n-1条走廊连接。但是每个房间里都有特别 的保护魔法,在它的作用下,我无法通过这个房间,也无法取得其中的钥匙。虽然我可以通过消耗能量来破坏房间里的魔法,但是我的能量是有限的。那么,如果我 最先站在1号房间(1号房间的保护魔法依然是有效的,也就是,如果不耗费能量,我无法通过1号房间,也无法取得房间中的钥匙),如果我拥有的能量为P,我 最多能取得多少钥匙?
输入格式
第一行包含两个非负整数,第一个为N,第二个为P。
接下来n行,按1~n的顺序描述了每个房间。第i+1行包含两个非负整数cost和keys,分别为第i件房取消魔法需要耗费的能量和房间内钥匙的数量。
接下来n-1行,每行两个非负整数x,y,表示x号房间和y号是连通的。
输出格式
一行一个整数,表示取得钥匙的最大值。
样例输入
5 5
1 2
1 1
1 1
2 3
3 4
1 2
1 3
2 4
2 5
样例输出
7
提示
对于20%的测试数据,有n<=20
对于30%的测试数据,有n<=30
对于所有测试数据,有p,n<=100, cost <= 32767, keys<= 32767
【题解】
多叉树转二叉树,左儿子右兄弟表示法
各种傻逼错各种卡
“将树转化为孩子兄弟表示法,由于根的左孩子还是它的孩子,右孩子是它的兄弟,因此:
树根获取资源,则左右孩子均可获取资源
树根不获取资源,则左孩子不能获取资源,右孩子可获取资源。
设f(i,j)表示以i为根结点的二叉树分配分配j的能量所获得的最多钥匙数,则有
”
——朱全民
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cmath> 6 #include <algorithm> 7 #define min(a, b) ((a) < (b) ? (a) : (b)) 8 #define max(a, b) ((a) > (b) ? (a) : (b)) 9 10 inline void read(int &x) 11 { 12 x = 0;char ch = getchar(), c = ch; 13 while(ch < '0' || ch > '9')c = ch, ch = getchar(); 14 while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar(); 15 if(c == '-')x = -x; 16 } 17 18 const int INF = 0x3f3f3f3f; 19 const int MAXN = 200 + 10; 20 const int MAXP = 200 + 10; 21 22 int n,p,dp[MAXN][MAXP],cost[MAXN],key[MAXN]; 23 24 struct Edge 25 { 26 int u,v,next; 27 Edge(int _u, int _v, int _next){u = _u;v = _v;next = _next;} 28 Edge(){} 29 }edge[MAXN]; 30 31 int head[MAXN],cnt; 32 33 void insert(int a, int b) 34 { 35 edge[++cnt] = Edge(a,b,head[a]); 36 head[a] = cnt; 37 } 38 39 struct Node 40 { 41 int l, r; 42 }node[MAXN]; 43 44 int b[MAXN]; 45 46 void dfs(int u) 47 { 48 b[u] = 1; 49 int kid1 = 0, kid2 = 0; 50 for(register int pos = head[u];pos;pos = edge[pos].next) 51 { 52 int v = edge[pos].v; 53 if(!b[v]) 54 { 55 if(!kid1) 56 { 57 kid1 = v; 58 node[u].l = v; 59 } 60 else node[kid1].r = v, kid1 = v; 61 dfs(v); 62 } 63 } 64 } 65 66 int bb[MAXN]; 67 68 void DP(int u) 69 { 70 if(!u)return; 71 bb[u] = 1; 72 if(!bb[node[u].l])DP(node[u].l); 73 if(!bb[node[u].r])DP(node[u].r); 74 for(register int i = 0;i <= p;++ i) 75 { 76 for(register int j = 0;j <= p;++ j) 77 if(i - cost[u] - j >= 0)dp[u][i] = max(dp[node[u].l][j] + key[u] + dp[node[u].r][i - cost[u] - j], dp[u][i]); 78 else dp[u][i] = max(dp[node[u].r][i], dp[u][i]); 79 } 80 } 81 82 int main() 83 { 84 read(n), read(p); 85 register int tmp1, tmp2; 86 for(register int i = 1;i <= n;++ i) read(cost[i]), read(key[i]); 87 for(register int i = 1;i < n;++ i) 88 { 89 read(tmp1), read(tmp2); 90 insert(tmp1, tmp2); 91 insert(tmp2, tmp1); 92 } 93 dfs(1); 94 DP(1); 95 printf("%d", dp[1][p]); 96 return 0; 97 }