码迷,mamicode.com
首页 > Web开发 > 详细

poj3659 Cell Phone Network(最小支配集-树形dp)

时间:2015-08-26 14:03:09      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:点击打开链接

题目描述:给定一棵树,从中选取尽量少的点使每个点要么被选中,要么和被选中的点直接相连?

解题思路:树上的最小支配集,树形dp

dp[i][0]:选中i作为支配集

dp[i][1]:不选i作为支配集,但其子节点覆盖了i

dp[i][2]:不选i作为支配集,而且其子节点没有覆盖i


代码:

#pragma comment(linker,"/STACK:1024000000,1024000000")
#include <cstdio>
#include <cstring>
#include <iostream>
#define MAXN 10010
#define INF 1e9+7
using namespace std;
int head[MAXN],tol;
struct Edge{
    int v,next;
}edge[MAXN*2];
void addEdge(int u,int v){
    edge[tol].v=v;edge[tol].next=head[u];head[u]=tol++;
    edge[tol].v=u;edge[tol].next=head[v];head[v]=tol++;
}
int min(int a,int b){
    return a<b?a:b;
}
int dp[MAXN][3];
int n;
void DP(int u,int p){
    dp[u][2]=0;
    dp[u][0]=1;
    int sum=0,inc=INF;
    int k,to;
    bool s=false;
    for(k=head[u];k!=-1;k=edge[k].next){
        to=edge[k].v;
        if(to==p) continue;
        DP(to,u);
        dp[u][0]+=min(dp[to][0],min(dp[to][1],dp[to][2]));
        if(dp[to][0]<=dp[to][1]){
            sum+=dp[to][0];
            s=true;
        }
        else
        {
            sum+=dp[to][1];
            inc=min(inc,dp[to][0]-dp[to][1]);
        }
        if(dp[to][1]!=INF&&dp[u][2]!=INF) dp[u][2]+=dp[to][1];
        else dp[u][2]=INF;
    }
    if(inc==INF&&!s) dp[u][1]=INF;
    else{
        dp[u][1]=sum;
        if(!s) dp[u][1]+=inc;
    }
}
int main(){
    while(scanf("%d",&n)!=EOF){
        tol=0;memset(head,-1,sizeof(head));
        int u,v;
        for(int i=0;i<n-1;++i){scanf("%d%d",&u,&v);addEdge(u,v);}
        DP(1,1);
        printf("%d\n",min(min(dp[1][0],dp[1][1]),dp[1][2]+1));
    }
    return 0;
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

poj3659 Cell Phone Network(最小支配集-树形dp)

标签:

原文地址:http://blog.csdn.net/mengxingyuanlove/article/details/48001645

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!