loj10157
太平王世子事件后,陆小凤成了皇上特聘的御前一品侍卫。
皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状,某些宫殿间可以互相望见。大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫殿安排看守所需的费用不同。
可是陆小凤手上的经费不足,无论如何也没法在每个宫殿都安置留守侍卫。
帮助陆小凤布置侍卫,在看守全部宫殿的前提下,使得花费的经费最少。
输入格式
输入中数据描述一棵树,描述如下:
第一行 n,表示树中结点的数目。
第二行至第 n+1行,每行描述每个宫殿结点信息,依次为:该宫殿结点标号 i(0<i≤n),在该宫殿安置侍卫所需的经费 k,该边的儿子数 m,接下来 m 个数,分别是这个节点的 m 个儿子的标号r1,r2,⋯,rm。
对于一个 n 个结点的树,结点标号在 1 到 n 之间,且标号不重复。
输出格式
输出最少的经费
数据范围与提示
对于 100% 的数据,0<n≤1500。
______________________________________________________________________________________________________________________
f[u][0]:u点由父节点看守
f[u][1]:u点由子节点看守
f[u][2]:u点由自己看守
f[u][0]=sum(min(f[v][1],f[v][2]))
f[u][2]=sum(min(f[v][0],f[v][1],f[v][2]))+fy[u]
f[u][1]=sum(min(f[v][1],f[v][2]))+min(f[v][2]-min(f[v][1],f[v][2]))
注意f[u][1]的推导
______________________________________________________________________________________________________________________
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1510; 4 int n,root; 5 int fy[maxn],rd[maxn]; 6 struct edge 7 { 8 int u,v,nxt; 9 }e[maxn]; 10 int head[maxn],js; 11 void addage(int u,int v) 12 { 13 e[++js].u=u;e[js].v=v; 14 e[js].nxt=head[u];head[u]=js; 15 } 16 int f[maxn][3]; 17 int minn(int a,int b,int c) 18 { 19 int tp=a; 20 if(tp>b)tp=b; 21 if(tp>c)tp=c; 22 return tp; 23 } 24 void dp(int u,int fa) 25 { 26 f[u][0]=f[u][1]=0; 27 f[u][2]=fy[u]; 28 int tp=0x7fffffff; 29 for(int i=head[u];i;i=e[i].nxt) 30 { 31 int v=e[i].v; 32 dp(v,u); 33 f[u][0]+=min(f[v][1],f[v][2]); 34 f[u][2]+=minn(f[v][0],f[v][1],f[v][2]); 35 f[u][1]+=min(f[v][1],f[v][2]); 36 tp=min(tp,f[v][2]-min(f[v][1],f[v][2])); 37 } 38 f[u][1]+=tp; 39 } 40 int main() 41 { 42 scanf("%d",&n); 43 for(int u,nm,v,i=1;i<=n;++i) 44 { 45 scanf("%d",&u); 46 scanf("%d%d",&fy[u],&nm); 47 for(int j=0;j<nm;++j) 48 { 49 scanf("%d",&v); 50 rd[v]++; 51 addage(u,v); 52 } 53 } 54 for(int i=1;i<=n;++i) 55 { 56 if(rd[i]==0) 57 { 58 root=i; 59 break; 60 } 61 } 62 dp(root,0); 63 cout<<min(f[root][1],f[root][2]); 64 return 0; 65 }