zoukankan      html  css  js  c++  java
  • UVA1218--树形DP

    没有看书和题解做的一道树形DP题,思路很清晰。。只是debug上花了很久的时间才发现看错了条件。。并不是每个点都只能和一台服务器相邻,而是非服务器的点只能和一台服务器相邻。。看错了一个条件差距大了去了。。

    设d[u][col][fcol]代表节点为u,颜色为col,父亲节点为fa,颜色为fcol时的最小服务器数量。col值为1代表服务器,0代表计算机,则转移方程:

    d[u][1][x]:只要col为1,则每个节点既可以是服务器也可以不是;

    d[u][0][1]:节点u是不服务器,fa是服务器,则u的子节点都不是服务器;

    d[u][0][0]:节点u和fa都不是服务器

    状态转移:dp(u,1,x)=sum{min(dp(v,0,u,1),dp(v,1,u,1))} + 1;

    dp(u,0,1) = sum{dp(v,0,u,0)};

    dp(u,0,0)=min{dp(u,0,1)-dp(v,0,0)+dp(v,1,x)};

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<cstring>
    #include<cmath>
    #include<sstream>
    #include<climits>
    #define INF 1000000
    using namespace std;
    const int maxn = 10005;
    
    int n;
    int u,v;
    vector<int> g[maxn];
    int ed;
    int d[maxn][2][2];
    
    int dp(int u,int col,int fa,int fcol)
    {
        if(d[u][col][fcol] > -1) return d[u][col][fcol];
    
        if(col == 1){
            //if(g[u].size() == 1&&g[u][0] == fa) return d[u][col][fcol] = 1;
            int sum = 1;
            for(int i = 0; i < g[u].size(); ++i){
                int v = g[u][i];
                if(v != fa)
                sum+=min(dp(v,0,u,1),dp(v,1,u,1));
            }
            return d[u][col][fcol] = sum;
        }
        else if(fcol == 1&&col == 0){
            //if(g[u].size() == 1&&g[u][0] == fa) return d[u][col][fcol] = 0;
            int sum = 0;
            for(int i = 0; i < g[u].size(); ++i){
                int v = g[u][i];
                if(v != fa){
                    sum+=dp(v,0,u,0);
                }
            }
            return d[u][col][fcol] = sum;
        }
        else if(fcol == 0&&col == 0)
        {
            //if(g[u].size() == 1&&g[u][0] == fa) return d[u][col][fcol] = INF;
            int sum = dp(u,0,fa,1);//cout<<sum<<"***"<<endl;
            int ans = INF;
            for(int i = 0; i < g[u].size(); ++i){
                int v = g[u][i];
                if(v != fa){
                    ans = min(ans,sum + dp(v,1,u,0)- dp(v,0,u,0));
                }
            }
            return d[u][col][fcol] = ans;
        }
    }
    
    int main()
    {
        //freopen("in","r",stdin);
        while(~scanf("%d",&n))
        {
            memset(d,-1,sizeof(d));
            for(int i = 1; i <= n-1; ++i)
            {
                scanf("%d%d",&u,&v);
                g[u].push_back(v);
                g[v].push_back(u);
            }
            cout<<min(dp(1,0,-1,0),dp(1,1,-1,0))<<endl;
            for(int i = 1; i <= n; ++i) g[i].clear();
            cin>>ed;
            if(ed == -1) return 0;
        }
    }
  • 相关阅读:
    sql2000/2005获取表的列SQL文
    SQL Server未公开的两个存储过程
    HNOI2008 玩具装箱
    noi2004 郁闷的出纳员
    狼抓兔子(平面图转对偶图求最短路)
    pku1917 Automatic Poetry
    幸福的道路
    闲话电子商店(eshop)的设计和经营2
    基金清仓,晚上欢聚
    早上想来想去,把自己的基金卖了1/5
  • 原文地址:https://www.cnblogs.com/Norlan/p/4814547.html
Copyright © 2011-2022 走看看