一本通1579【例 5】皇宫看守

1579: 【例 5】皇宫看守

时间限制: 1000 ms         内存限制: 524288 KB

题目描述

太平王世子事件后,陆小凤成了皇上特聘的御前一品侍卫。

皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状,某些宫殿间可以互相望见。大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫殿安排看守所需的费用不同。

可是陆小凤手上的经费不足,无论如何也没法在每个宫殿都安置留守侍卫。

帮助陆小凤布置侍卫,在看守全部宫殿的前提下,使得花费的经费最少。

Picture1

输入格式

输入中数据描述一棵树,描述如下:

第一行 n,表示树中结点的数目。

第二行至第 n+1 行,每行描述每个宫殿结点信息,依次为:该宫殿结点标号 (0<in),在该宫殿安置侍卫所需的经费 k,该边的儿子数 m,接下来 m 个数,分别是这个节点的 m 个儿子的标号r1,r2,,rm

对于一个 n 个结点的树,结点标号在 1 到 n 之间,且标号不重复。

输出格式

输出最少的经费

样例

样例输入

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

样例解释

有六个区域被安排的情况如左图所示。

如右图,灰色点安排了警卫,2 号警卫可以观察 1,2,5,633 号警卫可以观察 1,3,4 号警卫可以观察 1,4。

总费用:16+5+4=25

Picture2 Picture3

数据范围与提示

对于 100% 的数据,0<n1500。

sol:这道题我开始看成了没有上司的舞会,GG了无数发后发现它观察的是点(那道题是边)

dp[x][0,1][0,1]表示那个点是否有哨兵,是否安全,然后暴力转移就ojbk了(其实dp[1][0]是不存在的,其实就三个)

#include <bits/stdc++.h>
using namespace std;
inline int read()
{
    int s=0;
    bool f=0;
    char ch=' ';
    while(!isdigit(ch))
    {
        f|=(ch=='-');
        ch=getchar();
    }
    while(isdigit(ch))
    {
        s=(s<<3)+(s<<1)+(ch^48);
        ch=getchar();
    }
    return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(long long x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x<10)
    {
        putchar(x+'0');
        return;
    }
    write(x/10);
    putchar((x%10)+'0');
    return;
}
inline void writeln(int x)
{
    write(x);
    putchar('
');
    return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) writeln(x)
const int N=1505,M=3005,inf=0x3f3f3f3f;
int n,Cost[N];
struct Tree
{
    int tot,Next[M],to[M],head[N];
    inline void add(int x,int y)
    {
        Next[++tot]=head[x];
        to[tot]=y;
        head[x]=tot;
        return;
    }
    long long dp[N][2][2];
    //第一维[0,1]表示这个点是否有士兵
    //第二维[0,1]表示这个点是否安全 
    inline void dfs(int x,int fa)
    {
        int i;
        long long Min=inf;
        bool bo=0;
        for(i=head[x];i;i=Next[i]) if(to[i]!=fa)
        {
            dfs(to[i],x);
            dp[x][0][0]+=dp[to[i]][0][1];
            if(dp[to[i]][0][1]>dp[to[i]][1][1]) bo=1;
            else Min=min(Min,dp[to[i]][1][1]-dp[to[i]][0][1]);
            dp[x][0][1]+=min(dp[to[i]][0][1],dp[to[i]][1][1]);
            dp[x][1][1]+=min(min(dp[to[i]][0][0],dp[to[i]][0][1]),dp[to[i]][1][1]);
        }
        if(!bo)dp[x][0][1]+=Min;
        dp[x][1][1]+=Cost[x];
        return;
    }
    inline void Solve()
    {
        dfs(1,0);
        Wl(min(dp[1][0][1],dp[1][1][1]));
        return;
    }
    inline void Init()
    {
        tot=0;
        memset(head,0,sizeof head);
        return;
    }
}T;
int main()
{
//    freopen("guard6.in","r",stdin);
//    freopen("my.out","w",stdout);
    int i;
    R(n);
    T.Init();
    for(i=1;i<=n;i++)
    {
        int rt,k,x;
        R(rt); R(Cost[rt]); R(k);
        while(k--) {R(x); T.add(rt,x); T.add(x,rt);}
    }
    T.Solve();
    return 0;
}
/*
input
6
1 30 3 2 3 4
2 16 2 5 6
3 5 0
4 4 0
5 11 0
6 5 0
output
25

input
1
1 2 0
output
2

input
9
2 16 3 1 3 4
1 8000 3 5 6 7
3 6000 1 8
4 8000 0
5 1 1 9
6 900 0
7 100 0
8 2 0
9 20 0
output
1019
*/
View Code
原文地址:https://www.cnblogs.com/gaojunonly1/p/10356326.html