hdu 1054 树形dp

来源:互联网 发布:小学语文课文配音软件 编辑:程序博客网 时间:2024/05/29 17:35

题意:

给定一棵树,在节点上放上士兵,一个士兵可以控制与他所在节点相连的所有的边;

求最少需要多少士兵;

dp[i][0]表示以i节点为根,并且i节点不放时最小值,(同理有dp[i][1])

对于dp[i][0],因为根节点i不放,那么为满足要求,他的所有儿子都要放(这样才能保证i与儿子之间的边被覆盖)

而对于dp[i][1],儿子节点可放可不放,取min;


dp[i][0]+=dp[k][1];       (k为儿子节点)

dp[i][1]+=(dp[k][0],dp[k][1]) ;

dp[i][1]++;(i节点要放一个)


#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <vector>#define inf 1000000000;using namespace std;int dp[2222][2];int n;vector < int >v[1555];void dfs(int x){    int i,j,k,l=v[x].size();    if(l==0)    {        dp[x][0]=0;        dp[x][1]=1;        return ;    }    for(i=0;i<l;i++)    {        dfs(v[x][i]);    }    int tmp=0;    for(i=0;i<l;i++)    {        k=v[x][i];        dp[x][0]+=dp[k][1];        tmp+=min(dp[k][0],dp[k][1]);    }    dp[x][1]=tmp+1;}int a[1555];int main(){    int i,j,k,l,m;    while(cin>>n)    {        char s[22];        for(i=0;i<n;i++)        {            v[i].clear();        }        memset(a,0,sizeof(a));        memset(dp,0,sizeof(dp));        for(i=0;i<n;i++)        {            int aa,bb;            scanf("%d:(%d)", &aa, &bb);            for(j=0;j<bb;j++)            {                cin>>k;                l=aa;                v[l].push_back(k);                a[k]=1;            }        }        if(n==1)        {            cout<<1<<endl;            continue;        }        for(i=0;i<n;i++)        {            if(a[i]==0)            break;        }        dfs(i);        cout<<min(dp[i][1],dp[i][0])<<endl;    }}

0 0