Vijos 1144 小胖守皇宫 [树形dp]
2016-08-01 18:50
176 查看
P1144小胖守皇宫
描述
huyichen世子事件后,xuzhenyi成了皇上特聘的御前一品侍卫。
皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状;某些宫殿间可以互相望见。大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫殿安排看守所需的费用不同。
可是xuzhenyi手上的经费不足,无论如何也没法在每个宫殿都安置留守侍卫。
帮助xuzhenyi布置侍卫,在看守全部宫殿的前提下,使得花费的经费最少。
输入格式
输入文件中数据表示一棵树,描述如下:
第1行 n,表示树中结点的数目。
第2行至第n+1n+1行,每行描述每个宫殿结点信息,依次为:该宫殿结点标号 i ( 0 < i ≤ n0 < i ≤ n ),在该宫殿安置侍卫所需的经费k,该点的儿子数m,接下来m个数,分别是这个节点的m个儿子的标号r1,r2,⋯,rmr1,r2,⋯,rm。
对于一个 n(0 < n ≤ 15000 < n ≤ 1500)个结点的树,结点标号在1到n之间,且标号不重复。保证经费总和不超过231−1231−1。
输出格式
输出文件仅包含一个数,为所求的最少的经费。
样例输入
6
1 30 3 2 3 4
2 16 2 5 6
3 5 0
4 4 0
5 11 0
6 5 0
样例输出
25
对于一个节点 u 有自己守、父亲守、儿子守 三种状态,那么如果对应用 0 1 2 表示
- dp[u][0] = ∑min(dp[v][0,1,2]) + cost[u]
- dp[u][1] = ∑min(dp[v][0,1]) 并且至少有一个取 0状态
- dp[u][2] = ∑dp[v][1]
对于dp[u][1]可以设 delta = min(dp[v][0] - dp[v][1]) , 那么如果delta > 0 说明没有一个儿子选了自己守,那么此时就要加上这个最小的差量
注意最后只去存在的状态,并且初值不存在的状态不应该太大, 否则累加时可能超出 INT
描述
huyichen世子事件后,xuzhenyi成了皇上特聘的御前一品侍卫。
皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状;某些宫殿间可以互相望见。大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫殿安排看守所需的费用不同。
可是xuzhenyi手上的经费不足,无论如何也没法在每个宫殿都安置留守侍卫。
帮助xuzhenyi布置侍卫,在看守全部宫殿的前提下,使得花费的经费最少。
输入格式
输入文件中数据表示一棵树,描述如下:
第1行 n,表示树中结点的数目。
第2行至第n+1n+1行,每行描述每个宫殿结点信息,依次为:该宫殿结点标号 i ( 0 < i ≤ n0 < i ≤ n ),在该宫殿安置侍卫所需的经费k,该点的儿子数m,接下来m个数,分别是这个节点的m个儿子的标号r1,r2,⋯,rmr1,r2,⋯,rm。
对于一个 n(0 < n ≤ 15000 < n ≤ 1500)个结点的树,结点标号在1到n之间,且标号不重复。保证经费总和不超过231−1231−1。
输出格式
输出文件仅包含一个数,为所求的最少的经费。
样例输入
6
1 30 3 2 3 4
2 16 2 5 6
3 5 0
4 4 0
5 11 0
6 5 0
样例输出
25
对于一个节点 u 有自己守、父亲守、儿子守 三种状态,那么如果对应用 0 1 2 表示
- dp[u][0] = ∑min(dp[v][0,1,2]) + cost[u]
- dp[u][1] = ∑min(dp[v][0,1]) 并且至少有一个取 0状态
- dp[u][2] = ∑dp[v][1]
对于dp[u][1]可以设 delta = min(dp[v][0] - dp[v][1]) , 那么如果delta > 0 说明没有一个儿子选了自己守,那么此时就要加上这个最小的差量
注意最后只去存在的状态,并且初值不存在的状态不应该太大, 否则累加时可能超出 INT
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<vector> #include<queue> #include<stack> #include<map> #include<set> #include<string> #include<iomanip> #include<ctime> #include<climits> #include<cctype> #include<algorithm> #ifdef WIN32 #define AUTO "%I64d" #else #define AUTO "%lld" #endif using namespace std; #define smax(x,tmp) x=max((x),(tmp)) #define smin(x,tmp) x=min((x),(tmp)) #define maxx(x1,x2,x3) max(max(x1,x2),x3) #define minn(x1,x2,x3) min(min(x1,x2),x3) const int INF=0x3f3f3f3f; const int maxn=1505; struct Edge { int to,next; }edge[maxn]; int head[maxn]; int maxedge; int in[maxn],cost[maxn]; int root,n; inline int find_root() { for(int i=1;i<=n;i++) if(!in[i]) return i; return -1; //default } inline void addedge(int u,int v) { edge[++maxedge]=(Edge){ v,head[u] }; head[u]=maxedge; in[v]++; } inline void init() { memset(head,-1,sizeof(head)); maxedge=-1; scanf("%d",&n); for(int i=1;i<=n;i++) { int u,cnt; scanf("%d",&u); scanf("%d%d",cost+u,&cnt); for(int i=1;i<=cnt;i++) { int tmp; scanf("%d",&tmp); addedge(u,tmp); } } root = find_root(); } int f[maxn][3]; void dfs(int u) { if(!~head[u]) { f[u][0] = cost[u]; f[u][1] = INF / maxn; // if INF here, easy to exceed the maxlimit of integer!!! f[u][2] = 0; return; } int delta=INF; for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].to; dfs(v); f[u][0] += minn(f[v][0] , f[v][1] ,f[v][2]); f[u][1] += min(f[v][0] , f[v][1]); f[u][2] += f[v][1]; smin (delta , f[v][0] - f[v][1]); } if(delta > 0) f[u][1] += delta; // indicates that no son chosed the status 0 f[u][0] += cost[u]; } int main() { freopen("emperor.in","r",stdin); freopen("emperor.out","w",stdout); init(); dfs(root); printf("%d",min(f[root][0] , f[root][1])); // mustn't use the fathe 4000 r status, 'coz of no existence Last WA !!! return 0; }
相关文章推荐
- Vijos 1144 小胖守皇宫 【树形DP】
- 小胖守皇宫 vijos1144 树形dp
- vijos1144.小胖守皇宫(树形DP)
- 【vijos1144】小胖守皇宫(树形DP)
- Vijos 1144 小胖守皇宫 【树形DP】
- VIJOS-P1144 小胖守皇宫(树形dp)
- vijos1144小胖守皇宫 [树规]
- Vijos[1144]小胖守皇宫 树动规
- Vijos 1144 小胖守皇宫
- 【vijos】【树形dp】佳佳的魔法药水
- VIJOS P1144 小胖守皇宫
- vijos1144守皇宫43分求指点
- Vijos 1180 选课 [树形dp]
- Vijos 1523 贪吃的九头龙 【树形DP】
- vijos 1642 班长的任务 树形dp
- Vijos 1523 贪吃的九头龙 【树形DP】
- bzoj 2645: Vijos1676 陶陶吃苹果 (树形DP)
- 【树形dp】vijos P1180 选课
- Vijos 1100 加分二叉树(树形DP)
- 集训-vijos选课(树形DP)