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\n", min(min(f[1][0], f[1][1]), f[1][2]));
        scanf("%d", &t1);
    }
    return 0;
}

转载于:https://www.cnblogs.com/MyNameIsPc/p/8867142.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值