来源:牛客网:

时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 10000K,其他语言20000K
64bit IO Format: %lld

题目描述

Bob enjoys playing computer games, especially strategic games, but sometimes he cannot find the solution fast enough and then he is very sad. Now he has the following problem. He must defend a medieval city, the roads of which form a tree. He has to put the minimum number of soldiers on the nodes so that they can observe all the edges. Can you help him?

Your program should find the minimum number of soldiers that Bob has to put for a given tree.

For example for the tree:
在这里插入图片描述

the solution is one soldier ( at the node 1).
输入描述:
The input contains several data sets in text format. Each data set represents a tree with the following description:

the number of nodes
the description of each node in the following format
node_identifier:(number_of_roads) node_identifier1 node_identifier2 ... node_identifiernumber_of_roads
or
node_identifier:(0)

The node identifiers are integer numbers between 0 and n-1, for n nodes (0 < n <= 1500);the number_of_roads in each line of input will no more than 10. Every edge appears only once in the input data.
输出描述:
The output should be printed on the standard output. For each given input data set, print one integer number in a single line that gives the result (the minimum number of soldiers). An example is given in the following:
示例1
输入
复制

4
0:(1) 1
1:(2) 2 3
2:(0)
3:(0)
5
3:(3) 1 4 2
1:(1) 0
2:(0)
0:(0)
4:(0)

输出
复制

1
2

题解:

试题:一个树,在一个节点放兵,周围的边就被守护,问最少放多少兵
确定状态:
dp[x][1]以x为根的子树全被看住且在x上放置士兵的最少所需的士兵数量
dp[x][0]以x为根的子树全被看住且在x上没有 放置士兵的最少所需的士兵数量.
确定状态方程:
dp[x][1]=1+∑min(dp[i][0],dp[i][1])//x上放了士兵,x的儿子们可放可不放
dp[x][0]=∑dp[i][1]//如果x不放士兵,x的儿子必须放
结果min(dp[root][0],dp[root][1])
i是x的儿子
相当于我们在考虑x点时,x的子节点都是被考虑完的,x能否被覆盖完全取决于自身或x的儿子

代码:

树型dp的代码都很像,就是把状态转移改改
这个代码貌似有点问题,我还在改(为什么牛客oj提交不上)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=1050;
vector<int>edge[maxn];
int ans=0;
int dp[maxn][4];
void dfs(int u,int fa)
{
    dp[u][1]=1;
    ans=max(ans,dp[u][1]); 
    for(int v:edge[u])
    {
        if(v==fa)continue;
        dfs(v,u);
        dp[u][1]+=max(dp[v][1],dp[v][0]);
        dp[u][0]+=dp[v][1];
    }
}
int n;
void init()
{
    memset(dp,0,sizeof(dp));
    for(int i=0;i<=n;i++)edge[i].clear();
}
int main()
{

    while(cin>>n)
    {
        init();

        for(int i=1;i<=n;i++)
        {
            int u,v,d;
            scanf("%d:(%d)",&u,&d);
            for(int i=1;i<=d;i++)
            {
                cin>>v;
                edge[u].push_back(v);
                edge[v].push_back(u);
            }

        }
        dfs(0,-1);
        cout<<min(dp[0][0],dp[0][1])<<endl;
    }

    return 0;
}