uva1218树形dp

题意:有n台机器形成树形结构。要求在其中一些机器上安装服务器,使得每台不是服务器的计算机恰好和一台服务器计算机相邻。求服务器最少的数量。

思路:所有机器分为3种:

      dp[u][0]:是服务器,故该节点的孩子任意。dp[u][0]=sum{min(dp[v][0],dp[v][1])}

      dp[u][1]:不是服务器,但父亲是服务器,故该节点的孩子不能有服务器。dp[u][1]=sum{dp[v][2]}

      dp[u][2]:不是服务器且其父亲也不是服务器,故给节点的恰好有一个孩子是服务器。遍历复杂度高,可用之前所算出的结果计算:d[u][2]=min(d[u][1]-d[v][2]+d[v][0])

      最后输出min(d[1][0],d[1][2]),因为作为根节点的1没有父亲,所以他的子节点不能没有服务器。所以没有dp[1][1]的情况。

      树形结构,但在输入联系的时候没有规定父亲和儿子,所以作为图来搜没有被访问过的点。

      队列用来记录每个节点的孩子。

      dfs

#include<bits/stdc++.h>
using namespace std;

int dp[10000+10][3];
vector<int>line[10000+10];
int vis[10000+10];

void dfs(int u)
{
    vis[u]=1;
    dp[u][0]=1;dp[u][1]=0;dp[u][2]=10000+10;
    queue<int>q;
    for(int i=0;i<line[u].size();i++)
    {
        int v=line[u][i];
        if(!vis[v])
        {
            dfs(v);
            q.push(v);
            dp[u][0]=dp[u][0]+min(dp[v][0],dp[v][1]);
            dp[u][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();
    }
    return;
}
int main()
{
    while(1)
    {
        int n;
        cin>>n;
        if(!n)continue;
        if(n==-1)break;
        memset(vis,0,sizeof(vis));
        for(int i=0;i<=n;i++)line[i].clear();
        for(int i=0;i<n-1;i++)
        {
            int a,b;
            cin>>a>>b;
            line[a].push_back(b);
            line[b].push_back(a);
        }
        dfs(1);
        cout<<min(dp[1][0],dp[1][2])<<endl;
    }
    return 0;
}

 

posted @ 2016-07-19 16:48  哲贤  阅读(131)  评论(0编辑  收藏  举报