Description
太平王世子事件后,陆小凤成了皇上特聘的御前一品侍卫。
皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状;某些宫殿间可以互相望见。大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫殿安排看守所需的费用不同。
可是陆小凤手上的经费不足,无论如何也没法在每个宫殿都安置留守侍卫。
Solution
这是去年的坑了现在才填上,我果然还是太弱了
考虑树形dp,f[i]表示i放侍卫且i和i的子树全被看见的最小代价,g[i]表示i不放侍卫且i和i的子树全被看见的最小代价,h[i]表示i不放侍卫且只有i的子树全被看见的最小代价,那么转移就很明了了
这里INF不能太大,嗯在算g[i]的时候有可能会爆的
Code
#include <stdio.h>
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define erg(i, st) for (int i = ls[st]; i; i = e[i].next)
#define min(x, y) (x)<(y)?(x):(y)
#define INF 0x3f3f3f3f / 10
#define N 2001
#define E N * 2 + 1
struct edge{int x, y, next;}e[E];
int ind[N], ls[N];
inline void addEdge(int &cnt, int x, int y){
cnt += 1; e[cnt] = (edge){x, y, ls[x]}; ls[x] = cnt;
ind[y] += 1;
}
int w[N], f[N], g[N], h[N];
inline void dfs(int now){
f[now] = w[now];
erg(i, now){
dfs(e[i].y);
}
bool flag = false;
erg(i, now){
f[now] += min(min(g[e[i].y], h[e[i].y]), f[e[i].y]);
if (f[e[i].y] <= g[e[i].y]){
g[now] += f[e[i].y];
flag = true;
}else{
g[now] += g[e[i].y];
}
h[now] += g[e[i].y];
}
if (!flag){
int mnFG = INF;
erg(i, now){
mnFG = min(mnFG, f[e[i].y] - g[e[i].y]);
}
g[now] += mnFG;
}
}
int main(void){
int n;
scanf("%d", &n);
int edgeCnt = 0;
rep(i, 1, n){
int x;
scanf("%d", &x);
scanf("%d", &w[x]);
int tmp;
scanf("%d", &tmp);
while (tmp --){
int y;
scanf("%d", &y);
addEdge(edgeCnt, x, y);
}
}
int root;
rep(i, 1, n){
if (!ind[i]){
root = i;
break;
}
}
dfs(root);
printf("%d\n", min(f[root], g[root]));
return 0;
}