JDOJ-1310: VIJOS-P1144 小胖守皇宫

[文章目录]

Description

一棵树;某些宫殿间可以互相望见,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫殿安排看守所需的费用不同。帮助xuzhenyi布置侍卫,在看守全部宫殿的前提下,使得花费的经费最少。

树形DP,我的天啊,这道题不知道为什么调了好久才AC,最小支配集+点权。
首先有三个状态:
self[x]表示点x自己支配自己时子树的最优解
none[x]表示x未被支配时,子树的最优解(后改成未知点x是否被支配的最优解)
son[x]表示x被自己的儿子支配时的最优
方程:x为y的fa
self[x]+=min(self[y],none[y],son[y]);
none[x]+=min(self[y],son[y]);(这样就防止了数据溢出,因为光是son的话有可能所有的son都是极大值,也就是所有的son都是叶子结点)
son[x]=min(之前最优none[x]+selfy,son[x]+min(son[y],self[y]));
记得要初始化0x3f,然后记得self+=val;

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n,t,a,b;
int h[1600],to[3100],nxt[3100],cnt;
int none[1600],self[1600],son[1600];
void add(int x,int y)
{
    to[++cnt]=y;
    nxt[cnt]=h[x];
    h[x]=cnt;
}
void dfs(int x,int pre)
{
    none[x]=0;
    for(int i=h[x];i;i=nxt[i])
    {
        if(to[i]==pre) continue;
        dfs(to[i],x);
        son[x]=min(none[x]+self[to[i]],son[x]+min(self[to[i]],son[to[i]]) );
        self[x]+=min(none[to[i]],min(self[to[i]],son[to[i]]) );
        none[x]+=min(son[to[i]],self[to[i]]);
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&b);
        scanf("%d",&self[b]);
        scanf("%d",&t);
        for(int j=1;j<=t;j++)
        {
            scanf("%d",&a);
            add(b,a);
            add(a,b);
        }
    }
    for(int i=1;i<=n;i++)
        son[i]=none[i]=0x3f3f3f3f;
    dfs(1,0);
    printf("%d",min(self[1],son[1]));
    return 0;
}

 

发表评论

邮箱地址不会被公开。 必填项已用*标注