poj 3689 树形dp

思路: 每个点有三种状态,本身有塔,被子节点的塔覆盖,被父节点的塔覆盖。

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<string>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Maxn 10100
#define Maxm 100010
#define LL __int64
#define Abs(x) ((x)>0?(x):(-x))
#define lson(x) (x<<1)
#define rson(x) (x<<1|1)
#define inf 1000000
#define Mod 1000000007
using namespace std;
int dp[Maxn][3],head[Maxn],vi[Maxn],e;
struct Edge{
    int u,v,val,next;
}edge[Maxn*2];
void init()
{
    memset(dp,0,sizeof(dp));
    memset(head,-1,sizeof(head));
    memset(vi,0,sizeof(vi));
    e=0;
}
void add(int u,int v)
{
    edge[e].u=u,edge[e].v=v,edge[e].next=head[u],head[u]=e++;
    edge[e].u=v,edge[e].v=u,edge[e].next=head[v],head[v]=e++;
}
inline int min(int a,int b,int c)
{
    a=a<b?a:b;
    return a<c?a:c;
}
void dfs(int u)
{
    int i,v;
    vi[u]=1;
    dp[u][0]=1;//有信息塔
    dp[u][1]=0;//由前覆盖
    dp[u][2]=0;//由后覆盖
    int sum=0,f=0,min1=inf;
    for(i=head[u];i!=-1;i=edge[i].next){
        v=edge[i].v;
        if(vi[v]) continue;
        dfs(v);
        dp[u][0]+=min(dp[v][0],dp[v][1],dp[v][2]);
        dp[u][2]+=min(dp[v][1],dp[v][0]);
        if(dp[v][0]<=dp[v][1]){
            sum+=dp[v][0];
            f=1;
        }
        else{
            if(dp[v][0]-dp[v][1]<min1){
                min1=dp[v][0]-dp[v][1];
            }
            sum+=dp[v][1];
        }
    }
    if(f) dp[u][1]=sum;
    else dp[u][1]=sum+min1;
}
int main()
{
    int n,i,j,u,v;
    while(scanf("%d",&n)!=EOF){
        init();
        for(i=1;i<n;i++){
            scanf("%d%d",&u,&v);
            add(u,v);
        }
        dfs(1);
        printf("%d\n",min(dp[1][0],dp[1][1]));
    }
    return 0;
}

 

posted @ 2013-09-02 13:58  fangguo  阅读(205)  评论(0编辑  收藏  举报