UVa 1218 (树形dp)

很久之前做的题,今天又做到了,顺手来补一下题解。。。

题意:有n台电脑,互相以无根树的方式连接。现在将其中一些电脑作为服务器,且要求每台电脑有且必须连接一台服务器。(不包括本身是服务器的电脑),问需要多少台电脑作为服务器。

思路:

设u是父亲,v是u的孩子。

d(u,0):u本身是服务器;

d(u,1):u不是服务器,u的父亲是服务器。

d(u,2):u不是服务器,u的父亲不是服务器,u的孩子必须有且只有一个是服务器。

那么就能得出

d(u,0)  = Sum(d(v,1));

d(u,1) = Sum(d(v,2));

d(u,2) = min(d(u,2), d(u,1)-d(v,2)+d(v,0));

代码:注意d[u][2]不要初始化inf,这样累加的时候会超上限,因为这个wa了好多次。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>

using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 10010;
int n;
vector<int>g[maxn];
int dp[maxn][3];
int vis[maxn];

void dfs(int u)
{
    queue<int>q;
    vis[u] = 1;
    dp[u][0] = 1;
    dp[u][1] = 0;
    dp[u][2] = n;
    for(int i = 0; i < g[u].size(); i++)
    {
        int v = g[u][i];
        if(!vis[v])
        {
            dfs(v);
            q.push(v);
            dp[u][0] += min(dp[v][0],dp[v][1]);
            dp[u][1] += dp[v][2];
        }
    }
    while(!q.empty())
    {
        dp[u][2] = min(dp[u][2],dp[u][1]-dp[q.front()][2]+dp[q.front()][0]);
        q.pop();
    }
}

int main()
{
    while(cin>>n)
    {
        if(n==0)
            continue;
        if(n==-1)
            break;
        for(int i = 1; i <= n; i++)
            g[i].clear();
        for(int i = 0; i < n-1; i++)
        {
            int u,v;
            cin >> u >> v;
            g[u].push_back(v);
            g[v].push_back(u);
        }
        memset(vis,0,sizeof(vis));
        dfs(1);
        int ans = min(dp[1][0],dp[1][2]);
        cout<<ans<<endl;
    }
    return 0;
}




  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值