码迷,mamicode.com
首页 > 其他好文 > 详细

JDOJ-1310: VIJOS-P1144 小胖守皇宫

时间:2018-04-23 22:37:03      阅读:195      评论:0      收藏:0      [点我收藏+]

标签:node   can   void   n+1   初始   hint   分享图片   帮助   输出   

1310: VIJOS-P1144 小胖守皇宫

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 141  Solved: 64
[Submit][Status][Web Board]

Description

huyichen世子事件后,xuzhenyi成了皇上特聘的御前一品侍卫。 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状;某些宫殿间可以互相望见。大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫殿安排看守所需的费用不同。 可是xuzhenyi手上的经费不足,无论如何也没法在每个宫殿都安置留守侍卫。 帮助xuzhenyi布置侍卫,在看守全部宫殿的前提下,使得花费的经费最少。

Input

输入文件中数据表示一棵树,描述如下: 第1行  n,表示树中结点的数目。 第2行至第n+1行,每行描述每个宫殿结点信息,依次为:该宫殿结点标号i(0< i< =n),在该宫殿安置侍卫所需的经费k,该边的儿子数m,接下来m个数,分别是这个节点的m个儿子的标号r1,r2,...,rm。 对于一个n(0  <   n  < =  1500)个结点的树,结点标号在1到n之间,且标号不重复。

Output

输出文件仅包含一个数,为所求的最少的经费。

Sample Input

6 1 30 3 2 3 4 2 16 2 5 6 3 5 0 4 4 0 5 11 0 6 5 0

Sample Output

25

HINT

 

技术分享图片

总结:树形dp

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;
}

  

JDOJ-1310: VIJOS-P1144 小胖守皇宫

标签:node   can   void   n+1   初始   hint   分享图片   帮助   输出   

原文地址:https://www.cnblogs.com/oi-forever/p/8922028.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!