zoukankan      html  css  js  c++  java
  • Perfect service(树形dp)

    Perfect service(树形dp)

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

    这种类似独立集的树形dp问题,都可以将同一个结点的状态分成几类。这里用(f[i][0])表示i是服务器,(f[i][1])表示i不是服务器,但是i的父亲是服务器。(f[i][2])表示i和i的父亲都不是服务器。

    那么就可以写出转移方程:(f[i][0]=sum(min(f[v][0], f[v][1]))+1)(f[i][1]=sum(f[v][2]))(f[i][2]=min(f[i][1]-f[v][2]+f[v][0]))。时间复杂度为(O(n))

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int maxn=1e4+5;
    
    int cntedge, fir[maxn];
    struct Edge{
        int to, next;
    }e[maxn];
    void RESET(){ cntedge=0; memset(fir, 0, sizeof(fir)); }
    void addedge(int x, int y){
        Edge &e1=e[++cntedge];
        e1.to=y; e1.next=fir[x]; fir[x]=cntedge;
    }
    
    int n, f[maxn][3];  //0:自己是 1:父亲是 2:自己和父亲都不是
    
    //也可以保存访问顺序,在外部访问
    void dfs(int u, int par){
        f[u][0]=1; f[u][1]=0;
        f[u][2]=n; int v;
        for (int i=fir[u]; i; i=e[i].next){
            if ((v=e[i].to)==par) continue;
            dfs(v, u);
            f[u][0]+=min(f[v][0], f[v][1]);
            f[u][1]+=f[v][2];
        }
        for (int i=fir[u]; i; i=e[i].next){
            if ((v=e[i].to)==par) continue;
            f[u][2]=min(f[u][2], f[u][1]-f[v][2]+f[v][0]);
        }
    }
    
    int main(){
        int t1=0, t2;
        while (~t1&&~scanf("%d", &n)){
            RESET();
            for (int i=1; i<n; ++i){
                scanf("%d%d", &t1, &t2);
                addedge(t1, t2); addedge(t2, t1); }
            dfs(1, 0);
            printf("%d
    ", min(min(f[1][0], f[1][1]), f[1][2]));
            scanf("%d", &t1);
        }
        return 0;
    }
    
  • 相关阅读:
    欧几里得学习笔记
    卢卡斯定理学习笔记
    环相关问题
    BSGS学习笔记
    淘宝首页自动切换选项卡变换内容
    彻底弄懂CSS盒子模式(DIV布局快速入门)
    runoo' blog WEB2.0
    彻底弄懂CSS盒子模式
    CSS 样式切换
    js强贴收藏
  • 原文地址:https://www.cnblogs.com/MyNameIsPc/p/8867142.html
Copyright © 2011-2022 走看看