loj10157. 「一本通 5.2 例 5」皇宫看守

思路:

  例四是覆盖全部边,dp两个状态,例五是覆盖全部点,dp三个状态。

#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 = 1, cnt;
int head[maxn];
int go[maxn << 1];
int nxt[maxn << 1];

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

int val[maxn];

int dp[maxn][3];

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(val[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][2] = val[x];
    int minn = 0x3f3f3f3f, d = 0x3f3f3f3f;
    for(int i=head[x]; i; i=nxt[i]){
        if(go[i] != f[x]){
            DP(go[i]);
            dp[x][0] += min(dp[go[i]][1], dp[go[i]][2]);
            minn = min(dp[go[i]][1], dp[go[i]][2]);
            dp[x][1] += minn;
            d = min(d, dp[go[i]][2] - minn);
            dp[x][2] += min(min(dp[go[i]][0], dp[go[i]][1]), dp[go[i]][2]);
        }
    }
    dp[x][1] += d;
}
int main(void){
    init();
    DP(rt);
    printf("%d\n", min(dp[rt][2], dp[rt][1]));
}

 

posted @ 2018-08-17 09:26  junk_yao  阅读(207)  评论(0编辑  收藏  举报