洛谷P2016 战略游戏

题目描述:

Bob喜欢玩电脑游戏,特别是战略游戏。但是他经常无法找到快速玩过游戏的办法。现在他有个问题。

他要建立一个古城堡,城堡中的路形成一棵树。他要在这棵树的结点上放置最少数目的士兵,使得这些士兵能了望到所有的路。

注意,某个士兵在一个结点上时,与该结点相连的所有边将都可以被了望到。

请你编一程序,给定一树,帮Bob计算出他需要放置最少的士兵.

题解:

一看就是树形DP题。

我们设f(x) 表示选定 x, 保证子树合法,子树内所需要的最小点数。g(x) 表示不选择 x, 保证子树合法所需要的最小点数

可以推出:

f(x) = ∑min{f(son[x]), g(son[x])}

g(x) = ∑f(son[x])

附上代码:

#include<cstdio>
#define inf 1000000000
int n,a,b,c,idx,head[1501],f[1501][2];
struct Edge
{
    int to,next;
}edge[3001];
int min(int x,int y)
{
    if(x<y)
        return x;
    return y;
}
void addedge(int x,int y)
{
    ++idx;
    edge[idx].to=y;
    edge[idx].next=head[x];
    head[x]=idx;
}
void dfs(int x,int from)
{
    f[x][1]=1;
    f[x][0]=0;
    if(head[x]==0) f[x][0]=inf;
    for(int i=head[x];i;i=edge[i].next)
    {
        if(edge[i].to!=from)
        {
            dfs(edge[i].to,x);
            f[x][1]+=min(f[edge[i].to][1],f[edge[i].to][0]);
            f[x][0]+=f[edge[i].to][1];
        }
    }   
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&a,&b);a++;
        for(int j=1;j<=b;j++)
        {
            scanf("%d",&c);c++;
            addedge(a,c);
            addedge(c,a);
        }
    }
    dfs(1,0);
    printf("%d",min(f[1][1],f[1][0]));
} 

猜你喜欢

转载自www.cnblogs.com/jiangminghong/p/9810312.html