Vijos 1144 小胖守皇宫 【树形DP】
小胖守皇宫
描述
huyichen世子事件后,xuzhenyi成了皇上特聘的御前一品侍卫。
皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状;某些宫殿间可以互相望见。大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫殿安排看守所需的费用不同。
可是xuzhenyi手上的经费不足,无论如何也没法在每个宫殿都安置留守侍卫。
帮助xuzhenyi布置侍卫,在看守全部宫殿的前提下,使得花费的经费最少。
格式
输入格式
输入文件中数据表示一棵树,描述如下:
第1行 n,表示树中结点的数目。
第2行至第n+1n+1行,每行描述每个宫殿结点信息,依次为:该宫殿结点标号i(0<i \le n0<i≤n),在该宫殿安置侍卫所需的经费k,该点的儿子数m,接下来m个数,分别是这个节点的m个儿子的标号r_1, r_2, \cdots, r_mr1,r2,⋯,rm。
对于一个n(0 < n \le 15000<n≤1500)个结点的树,结点标号在1到n之间,且标号不重复。保证经费总和不超过2^31-1231−1。
输出格式
输出文件仅包含一个数,为所求的最少的经费。
样例1
样例输入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
样例输出1
25
限制
提示
如图
来源
huyichen
题目链接:
题目大意:
一个树形皇宫,每个结点可以放置看守,看守能够看到相邻的结点,不同结点有不同花费,问将所有点看守住的最小花费。
题目思路:
【树形DP】
F[X][0]表示结点X的父亲放了守卫的最小花费,
F[X][1]表示结点X自身放了守卫的最小花费,
F[X][2]表示结点X和父亲都不放守卫,X的其中一个儿子放了守卫的最小花费。
这样,父亲放了守卫,X可以选择放守卫(F[X][1]),或者可以是 儿子放或不放守卫(F[son][1],F[son][2])
自身放守卫,则儿子都是父亲放了守卫(F[son][0])
其中一个儿子放了守卫,则枚举哪个儿子是最优值。(F[son][1],F[son][0])
这样最终可以推出转移方程。
1 /****************************************************** 2 3 Author : Coolxxx 4 Copyright 2017 by Coolxxx. All rights reserved. 5 BLOG : http://blog.csdn.net/u010568270 6 7 ******************************************************/ 8 #include<bits/stdc++.h> 9 #pragma comment(linker,"/STACK:1024000000,1024000000") 10 #define abs(a) ((a)>0?(a):(-(a))) 11 #define lowbit(a) (a&(-a)) 12 #define sqr(a) ((a)*(a)) 13 #define mem(a,b) memset(a,b,sizeof(a)) 14 #define eps (1e-8) 15 #define J 10000 16 #define mod 1000000007 17 #define MAX 0x7f7f7f7f 18 #define PI 3.14159265358979323 19 #define N 1504 20 using namespace std; 21 typedef long long LL; 22 double anss; 23 LL aans; 24 int cas,cass; 25 int n,m,lll,ans; 26 int f[N][3]; 27 bool u[N]; 28 struct xxx 29 { 30 int num,c; 31 int s[N]; 32 }a[N]; 33 void dp(int now) 34 { 35 int i,j; 36 if(u[now])return; 37 if(!a[now].num) 38 { 39 f[now][1]=f[now][2]=a[now].c; 40 f[now][0]=0; 41 return; 42 } 43 for(i=1;i<=a[now].num;i++) 44 dp(a[now].s[i]); 45 f[now][0]=0; 46 for(j=1;j<=a[now].num;j++) 47 { 48 f[now][0]+=min(f[a[now].s[j]][1],f[a[now].s[j]][2]); 49 } 50 f[now][2]=MAX; 51 for(j=1;j<=a[now].num;j++) 52 { 53 f[now][2]=min(f[now][2],f[now][0]-min(f[a[now].s[j]][1],f[a[now].s[j]][2])+f[a[now].s[j]][1]); 54 } 55 f[now][1]=a[now].c; 56 for(j=1;j<=a[now].num;j++) 57 { 58 f[now][1]+=f[a[now].s[j]][0]; 59 } 60 f[now][0]=min(f[now][0],f[now][1]); 61 } 62 int main() 63 { 64 #ifndef ONLINE_JUDGE 65 // freopen("1.txt","r",stdin); 66 // freopen("2.txt","w",stdout); 67 #endif 68 int i,j,k; 69 int x,y,z; 70 // for(scanf("%d",&cass);cass;cass--) 71 // for(scanf("%d",&cas),cass=1;cass<=cas;cass++) 72 // while(~scanf("%s",s)) 73 while(~scanf("%d",&n)) 74 { 75 //mem(f,0x7f); 76 for(i=1;i<=n;i++) 77 { 78 scanf("%d",&x); 79 scanf("%d%d",&a[x].c,&a[x].num); 80 for(j=1;j<=a[x].num;j++) 81 { 82 scanf("%d",&a[x].s[j]); 83 u[a[x].s[j]]=1; 84 } 85 } 86 for(m=1;m<=n;m++)if(!u[m])break; 87 mem(u,0); 88 dp(m); 89 ans=min(f[m][1],f[m][2]); 90 printf("%d\n",ans); 91 } 92 return 0; 93 } 94 /* 95 // 96 97 // 98 */