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 
#include 
#include 
#include 
#include 
#include 

using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 10010;
int n;
vectorg[maxn];
int dp[maxn][3];
int vis[maxn];

void dfs(int u)
{
    queueq;
    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<


你可能感兴趣的:(dp,树形dp)