UVA1218 Perfect Service (树形dp)

题意分析

状态设计

dp[rt][0] d p [ r t ] [ 0 ] 表示本节点是服务器
dp[rt][1] d p [ r t ] [ 1 ] 表示本节点不是服务器,其父亲节点时服务器
dp[rt][2] d p [ r t ] [ 2 ] 表示本节点不是,其父节点也不是,而其子节点有一个是服务器

状态转移方程

dp[rt][0]=min(dp[v][0],dp[v][1])+1 d p [ r t ] [ 0 ] = ∑ m i n ( d p [ v ] [ 0 ] , d p [ v ] [ 1 ] ) + 1
dp[rt][1]=dp[v][2] d p [ r t ] [ 1 ] = ∑ d p [ v ] [ 2 ]
dp[rt][2]=min(dp[rt][1]dp[v][2]+dp[v][0]) d p [ r t ] [ 2 ] = m i n ( d p [ r t ] [ 1 ] − d p [ v ] [ 2 ] + d p [ v ] [ 0 ] )

初始条件

dp[rt][0]=1 d p [ r t ] [ 0 ] = 1
dp[rt][1]=0 d p [ r t ] [ 1 ] = 0
dp[rt][2]=INF d p [ r t ] [ 2 ] = I N F

代码总览

#include <bits/stdc++.h>
#define rep(i, a, b) for (int i = a; i <= b; ++i)
using namespace std;
const int nmax = 1e6 + 10;
const int INF = 0x3f3f3f3f;
typedef long long ll;
typedef double db;
typedef struct {
    int nxt, to;
} Edge;
Edge e[nmax << 1];
int head[nmax], tot = 0, n;
int dp[nmax][3];
void init() {
    memset(head, -1, sizeof head);
    tot = 0;
}
void add(int u, int v) {
    e[tot].to = v;
    e[tot].nxt = head[u];
    head[u] = tot++;
}
void getdp(int rt , int fa) {
    dp[rt][0] = 1;
    dp[rt][1] = 0;
    dp[rt][2] = 10100 + 1;
    for (int i = head[rt]; i != -1; i = e[i].nxt) {
        int v = e[i].to;
        if (v == fa) continue;
        else getdp(v, rt);
        dp[rt][0] += min(dp[v][0], dp[v][1]);
        dp[rt][1] += dp[v][2];
    }
    for (int i = head[rt]; i != -1; i = e[i].nxt) {
        int v = e[i].to;
        if (v == fa) continue;
        else dp[rt][2] = min(dp[rt][2], dp[rt][1] - dp[v][2] + dp[v][0]);
    }
}
int main() {
    while (scanf("%d", &n) != EOF && n != -1) {
        init();
        int u , v, temp;
        rep(i, 1, n - 1) {
            scanf("%d %d", &u, &v);
            add(u, v);
            add(v, u);
        }
        getdp(1, -1);
        printf("%d\n", min(dp[1][0], dp[1][2]));
        scanf("%d", &temp); if(temp == -1) break;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值