huyichen世子事件后,xuzhenyi成了皇上特聘的御前一品侍卫。 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状;某些宫殿间可以互相望见。大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫殿安排看守所需的费用不同。 可是xuzhenyi手上的经费不足,无论如何也没法在每个宫殿都安置留守侍卫。 帮助xuzhenyi布置侍卫,在看守全部宫殿的前提下,使得花费的经费最少。
标签:node can void n+1 初始 hint 分享图片 帮助 输出
huyichen世子事件后,xuzhenyi成了皇上特聘的御前一品侍卫。 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状;某些宫殿间可以互相望见。大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫殿安排看守所需的费用不同。 可是xuzhenyi手上的经费不足,无论如何也没法在每个宫殿都安置留守侍卫。 帮助xuzhenyi布置侍卫,在看守全部宫殿的前提下,使得花费的经费最少。
输入文件中数据表示一棵树,描述如下: 第1行 n,表示树中结点的数目。 第2行至第n+1行,每行描述每个宫殿结点信息,依次为:该宫殿结点标号i(0< i< =n),在该宫殿安置侍卫所需的经费k,该边的儿子数m,接下来m个数,分别是这个节点的m个儿子的标号r1,r2,...,rm。 对于一个n(0 < n < = 1500)个结点的树,结点标号在1到n之间,且标号不重复。
输出文件仅包含一个数,为所求的最少的经费。
dp[u][0] 被自己守
dp[u][1] 被父亲守
dp[u][2] 被儿子守
dp[u][0] += min(dp[v][1], min(dp[v][0], dp[v][2]));//儿子三种情况都可以
dp[u][1] += min(dp[v][0], dp[v][2]);//儿子只有这两种情况
for(枚举v)//枚举被哪个儿子守,利用已经计算好的dp[u][1]
dp[u][2] = min(dp[u][2], dp[u][1] - min(dp[v][0], dp[v][2]) + dp[v][0]);
初始化dp[u][0] = val[u], dp[u][2] = inf;
代码
#include<bits/stdc++.h> using namespace std; const int maxn = 3005; int n, head[maxn], cnt = 1; #define inf 10000007 int dp[maxn][3], val[maxn]; struct Node{ int v, nxt; } G[maxn]; void insert(int u, int v) { G[cnt] = (Node) {v, head[u]}; head[u] = cnt++; } int in[maxn]; /* dp[u][0] 被自己守 dp[u][1] 被父亲守 dp[u][2] 被儿子守 */ void DP(int x) { dp[x][0] = val[x]; dp[x][2] = inf; for (int i = head[x]; i; i = G[i].nxt) { int v = G[i].v; DP(v); dp[x][0] += min(dp[v][1], min(dp[v][0], dp[v][2])); dp[x][1] += min(dp[v][0], dp[v][2]); } for (int i = head[x]; i; i = G[i].nxt) { int v = G[i].v; dp[x][2] = min(dp[x][2], dp[x][1] - min(dp[v][0], dp[v][2]) + dp[v][0]); } } int main() { scanf("%d", &n); for (int i = 1; i <= n; ++i) { int x, m; scanf("%d", &x); scanf("%d%d", &val[x], &m); for (int j = 1; j <= m; ++j) { int y; scanf("%d", &y); insert(x, y); in[y]++; } } for (int i = 1; i <= n; ++i) { if(in[i] == 0) { DP(i); printf("%d\n", min(dp[i][0], dp[i][2])); return 0; } } return 0; }
标签:node can void n+1 初始 hint 分享图片 帮助 输出
原文地址:https://www.cnblogs.com/oi-forever/p/8922028.html