loj10156. 「一本通 5.2 例 4」战略游戏

思路:
  树形dp。

  dp[x][0]表示以x为根的子树中不选x的最少点数,dp[x][1]表示选x的最少点数。

#include<cstdio>
#include<iostream>
#include<cstdlib>
using namespace std;
const int maxn = 3010;
void qread(int &x){
    x = 0;
    register int ch = getchar();
    while(ch < '0' || ch > '9')    ch = getchar();
    while(ch >= '0' && ch <= '9')    x = 10 * x + ch - 48, ch = getchar();
}
int n, rt, cnt;
int head[maxn];
int go[maxn << 1];
int nxt[maxn << 1];

int d1[maxn];
int d2[maxn];

int f[maxn];
int deep[maxn];

int sum[maxn];

int dp[maxn][2];

void dfs(int x){
    for(int i = head[x]; i; i = nxt[i])
        if(!deep[go[i]]){
            f[go[i]] = x;
            deep[go[i]] = deep[x] + 1;
            dfs(go[i]);
        }
}
inline void init(){
    qread(n);
    for(int i=1; i<=n; ++i){
        int x, m;
        qread(x);
        qread(m);
        for(int j=1; j<=m; ++j){
            int y;
            qread(y);
            ++cnt;
            go[cnt] = y;
            nxt[cnt] = head[x];
            head[x] = cnt;
            ++cnt;
            go[cnt] = x;
            nxt[cnt] = head[y];
            head[y] = cnt;
        }
    }
    deep[rt] = 1;
    dfs(rt);
}

void DP(int x){
    dp[x][1] = 1;
    for(int i=head[x]; i; i=nxt[i]){
        if(go[i] != f[x]){
            DP(go[i]);
            dp[x][0] += dp[go[i]][1];
            dp[x][1] += min(dp[go[i]][1], dp[go[i]][0]);
        }
    }
}
int main(void){
    init();
    DP(rt);
    printf("%d\n", min(dp[rt][0], dp[rt][1]));
}

猜你喜欢

转载自www.cnblogs.com/junk-yao-blog/p/9491429.html
今日推荐