您的位置:首页 > 其它

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

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  动态规划 树形dp