#树形dp#jzoj 2005 皇宫看守

题目

宫殿间可以相互看见,在看守全部宫殿的前提下,使花费的经费最少。


分析

f [ i ] [ 0 ] i i
f [ i ] [ 1 ] i i
f [ i ] [ 2 ] i i
f [ i ] [ 0 ] = m i n ( f [ s o n ] [ 1 ] , f [ s o n ] [ 2 ] ) + d , f [ i ] [ 1 ] = m i n ( f [ s o n ] [ 1 ] , f [ s o n ] [ 2 ] ) + d
f [ i ] [ 2 ] = m i n ( f [ s o n ] [ 0 ] , f [ s o n ] [ 1 ] , f [ s o n ] [ 2 ] ) + c o s t [ i ]
d = m i n ( f [ s o n ] [ 2 ] m i n ( f [ s o n ] [ 1 ] , f [ s o n ] [ 2 ] ) )


代码

#include <cstdio>
#include <cctype>
using namespace std;
struct node{int y,next;}e[4001]; int ls[1501]; bool v[1501];
int n,k,f[1501][3],m,root,x,y,cost[1501];
int in(){
    int ans=0; char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) ans=ans*10+c-48,c=getchar();
    return ans;
}
int min(int a,int b){return (a<b)?a:b;}
void dp(int x,int last){
    int d=1e7;
    for (int i=ls[x];i;i=e[i].next){
        if (e[i].y==last) continue;//不退回去
        dp(e[i].y,x);
        f[x][0]+=min(f[e[i].y][1],f[e[i].y][2]);
        f[x][1]+=min(f[e[i].y][1],f[e[i].y][2]);
        d=min(d,f[e[i].y][2]-min(f[e[i].y][2],f[e[i].y][1]));
        f[x][2]+=min(f[e[i].y][2],min(f[e[i].y][0],f[e[i].y][1]));
    }
    f[x][1]+=d; f[x][2]+=cost[x];
}
int main(){
    freopen("guard.in","r",stdin);
    freopen("guard.out","w",stdout);
    n=in();
    for (int i=1;i<=n;i++){
        x=in(); cost[x]=in(); k=in();
        while (k--) e[++m]=(node){y=in(),ls[x]},ls[x]=m,v[y]=1;
    }
    for (root=1;root<=n&&v[root];root++);
    dp(root,0); return !printf("%d",min(f[root][1],f[root][2]));
}

猜你喜欢

转载自blog.csdn.net/sugar_free_mint/article/details/81045795
今日推荐