UVA ~ 1218 ~ Perfect Service (树形dp,最小支配集)

UVA ~ 1218 ~ Perfect Service (树形dp,最小支配集)

题意

UVA ~ 1218 ~ Perfect Service (树形dp,最小支配集)

补充

本题是多组输入输出,每组先输入N,然后输入N-1条边,然后在输入一个flag,flag=-1表示结束。
dp[u][2]=min(dp[u][2],dp[u][1]dp[v][2]+dp[v][0]);dp[u][2] = min(dp[u][2], dp[u][1] - dp[v][2] + dp[v][0]);,因为dp[u][1]dp[u][1]表示u不是服务器,但u的父亲是,所以u的所有子结点都不是服务器,dp[v][2]dp[v][2]表示的是v和v的父亲(u)都不是服务器。可得uu恰好有一个儿子是服务器的答案就是dp[u][1]dp[v][2]+dp[v][0]dp[u][1] - dp[v][2] + dp[v][0],此时v就是服务器。
需要注意INF溢出的问题,INF如果设置的过大,很多个INF相加会炸int,注意处理一下

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e4 + 5;
const int INF = 0x3f3f3f3f;
int n, dp[MAXN][3];
vector<int> G[MAXN];
void dfs(int u, int fa)
{
    dp[u][0] = 1;
    dp[u][1] = 0;
    dp[u][2] = INF;
    for (auto v : G[u])
    {
        if (v == fa) continue;
        dfs(v, u);
        dp[u][0] += min(dp[v][1], dp[v][0]); //u被占用           
        dp[u][1] += dp[v][2];                //u没被占用,但是u的父亲被占用
        dp[u][2] = min(dp[u][2], dp[u][1] - dp[v][2] + dp[v][0]); //u和u的父亲均没被占用
        if (dp[u][0] > INF) dp[u][0] = INF; //多个INF相加会超int上限
        if (dp[u][1] > INF) dp[u][1] = INF; //多个INF相加会超int上限
    }
}
int main()
{
    while (~scanf("%d", &n))
    {
        for (int i = 0; i <= n; i++) G[i].clear();
        for (int i = 1; i < n; i++)
        {
            int u, v; scanf("%d%d", &u, &v);
            G[u].emplace_back(v);
            G[v].emplace_back(u);
        }
        dfs(1, -1); 
        printf("%d\n", min(dp[1][0], dp[1][2]));
        int flag; scanf("%d", &flag);
        if (flag == -1) break;
    }
    return 0;
}
/*
6
1 3
2 3
3 4
4 5
4 6
0
2
1 2
-1
*/