UVA 1218 - Perfect Service (树形dp)

概要:有一树形结构的网络,要在一些结点安装服务器使得不是服务器的结点周围恰好有一个服务器,问服务器最小数量。

先转成有根树(枚举子节点的时候忽略其父亲),然后dp[u][s]表示u的子树安装服务器的最小数量,影响决策的是u是不是服务器以及其父节点的状态,所以s的取值为u是服务器(0),u不是服务器u的父亲是服务器(1),u不是服务器u的父亲也不是服务器(2)。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4+4;
int n;
vector<int> G[maxn];
#define PB push_back

int dp[maxn][3];

void dfs(int u,int fa)
{
    dp[u][1] = 0;
    dp[u][0] = 1;
    int sz = G[u].size();
    if(sz == 0){
        dp[u][2] = -maxn; // illegal
        return;
    }

    for(int i = 0; i < sz; i++){
        int v = G[u][i];
        if(v == fa) continue;
        dfs(v,u);
        dp[u][0] += min(dp[v][0],dp[v][1]);
        dp[u][1] += dp[v][2];
    }
    dp[u][2] = maxn;
    int &d2 = dp[u][2];
    for(int i = 0; i < sz; i++){
        int v = G[u][i];
        if(v == fa) continue;
        d2 = min(d2,dp[u][1]-dp[v][2]+dp[v][0]);
    }
}

void init()
{
    scanf("%d",&n);
    for(int i = 1; i <= n; i++) G[i].clear();
    for(int i = 1; i < n;i++){
        int u,v; scanf("%d%d",&u,&v);
        G[u].PB(v);
        G[v].PB(u);
    }

}

int main()
{
    //freopen("in.txt","r",stdin);
    int flag;
    do{
        init();
        dfs(1,-1);
        int ans = min(dp[1][0],dp[1][2]);
        printf("%d\n",ans);
        scanf("%d",&flag);
    }while(flag == 0);
    return 0;
}

 

posted @ 2015-08-20 09:52  陈瑞宇  阅读(241)  评论(0编辑  收藏  举报