zoukankan      html  css  js  c++  java
  • ZJOI2008 骑士(树型DP)

    ZJOI2008 骑士

    题目大意

    给出n个人的战斗力和每个人讨厌的人,然后问最大能有多大的战斗力

    solution

    简单粗暴的题意,有一丢丢背包的感觉
    那敢情就是DP了
    有点像没有上司的舞会,,,
    根据题意,骑士之间互相厌恶会形成一个环,任务就是找到这个环并且把它断开,然后对断开的两个端点分别求答案,然后取最优结果
    设定当前点为u
    断开的两个节点是u1和u2
    选取当前点的状态记为1,不选的话就是0
    那么数组就是dp[u][0],dp[u][1]
    从这两个中间取最大值即可
    最后将所有的DP值加和就是结果了

    第一眼应为想到要找环,所以本来打算写Tarjan判连通块
    然后去blogs验证思路的时候发现好像并不需要
    用到了一个神奇的东东——拓扑排序
    判环,拆分,统计入度和出度
    求和得到结果即可

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    inline int read(){
    	int x = 0, w = 1;
    	char ch = getchar();
    	for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') w = -1;
    	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
    	return x * w;
    }
    
    const int N = 1000000 + 10;
    int head[N], cnt = 1, size[N], r1, r2,p[N];
    struct Edge { 
        int to, next; 
    } edges[N << 1];
    
    bool vis[N], flag;
    long long ans, f[N][2];
    inline void add(int x, int y) {
        edges[++cnt].next = head[x];
        edges[cnt].to = y;
        head[x] = cnt;
    }
    
    inline void dfs(int x, int fa) {
        vis[x] = 1;
        size[++size[0]] = x;
        for (int i = head[x]; i; i = edges[i].next) {
            int v = edges[i].to;
            if (v == fa) continue;
            if (!vis[v]) dfs(v, x);
            else if (vis[v] && !flag) {
                flag = true;
                r1 = x, r2 = v;
            }
        }
    }
    
    inline void dfs2(int x, int fa) {
        f[x][0] = 0;
        f[x][1] = p[x];
        for (int i = head[x]; i; i = edges[i].next) {
            int v = edges[i].to;
            if (v && v != fa) {
                dfs2(v, x);
                f[x][1] += f[v][0];
                f[x][0] += max(f[v][0], f[v][1]);
            }
        }
    }
    
    inline void solve() {
        if (!flag) {
            int root = size[1];
            dfs2(root, -1);
            ans += max(f[root][0], f[root][1]);
        } else {
            long long maxv = -100;
            for (int i = head[r1]; i; i = edges[i].next) {
                if (edges[i].to == r2) {
                    edges[i].to = 0;
                    edges[i ^ 1].to = 0;
                    break;
                }
            }
            dfs2(r1, -1);
            maxv = max(maxv, f[r1][0]);
            dfs2(r2, -1);
            maxv = max(maxv, f[r2][0]);
            ans += maxv;
        }
    }
    
    int n;
    int main() {
        n = read();
        int x, y;
        for (int i = 1; i <= n; i++){
            p[i] = read();
            x = read();
            add(x, i);
            add(i, x);
        }
        for (int i = 1; i <= n; i++) {
            if (!vis[i]) {
                size[0] = 0;
                flag = false;
                dfs(i, -1);
                solve();
            }
        }
        printf("%lld", ans);
        return 0;
    }
    
  • 相关阅读:
    与众不同 windows phone (50)
    与众不同 windows phone (49)
    重新想象 Windows 8.1 Store Apps (93)
    重新想象 Windows 8.1 Store Apps 系列文章索引
    重新想象 Windows 8.1 Store Apps (92)
    重新想象 Windows 8.1 Store Apps (91)
    重新想象 Windows 8.1 Store Apps (90)
    重新想象 Windows 8.1 Store Apps (89)
    重新想象 Windows 8.1 Store Apps (88)
    重新想象 Windows 8.1 Store Apps (87)
  • 原文地址:https://www.cnblogs.com/rui-4825/p/12769180.html
Copyright © 2011-2022 走看看