BZOJ 1040. [ZJOI2008] Knight

 

DP on forest ring.

I just started to think about is to find the ring, then every point on the ring and its sub-tree shrunk to a point, it becomes a DP on the ring. Then it is not forced to take the first and the last one is not forced to take.

Read other people's explanations can be found not so much trouble, as long as the two find any adjacent ring, forced to put the edge off, and then two or DP on the line.

DP of the equation is more naive.

#include <bits/stdc++.h>

namespace IO {
    char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh = '\n';
    int p, p3 = -1;
    void read() {}
    void print() {}
    inline int getc() {
        return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++;
    }
    inline void flush() {
        fwrite(buf2, 1, p3 + 1, stdout), p3 = -1;
    }
    template <typename T, typename... T2>
    inline void read(T &x, T2 &... oth) {
        T f = 1; x = 0;
        char ch = getc();
        while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getc(); }
        while (isdigit(ch)) { x = x * 10 + ch - 48; ch = getc(); }
        x *= f;
        read(oth...);
    }
    template <typename T, typename... T2>
    inline void print(T x, T2... oth) {
        if (p3 > 1 << 20) flush();
        if (x < 0) buf2[++p3] = 45, x = -x;
        do {
            a[++p] = x % 10 + 48;
        } while (x /= 10);
        do {
            buf2[++p3] = a[p];
        } while (--p);
        buf2[++p3] = hh;
        print(oth...);
    }
}

#define ll long long
const int N = 1e6 + 7;
int n, fa[N], root, _root;
ll dp[N][2], val[N];
bool vis[N];
int head[N];
struct E {
    int v, ne;
} e[N << 1];
int cnt = 1, ban;

void add(int u, int v) {
    e [ ++ cnt] .v = v; e [cnt] .ne = head [ u]; head [u] = cnt;
}

void dfs(int u, int f) {
    vis[u] = 1;
    for (int i = head[u]; i; i = e[i].ne) {
        int v = e[i].v;
        if (v == f) continue;
        if (vis[v]) {
            root = u, _root = v;
            board = i;
        } else {
            dfs (v, u);
        }
    }
}

void DP(int u, int f) {
    dp[u][0] = 0; dp[u][1] = val[u];
    for (int i = head[u]; i; i = e[i].ne) {
        int v = e[i].v;
        if (v == f || i == ban || i == (ban ^ 1)) continue;
        DP(v, u);
        dp[u][0] += std::max(dp[v][0], dp[v][1]);
        dp[u][1] += dp[v][0];
    }
}

int main () {
    IO::read(n);
    for (int i = 1, u; i <= n; i++)
        IO::read(val[i], u), add(u, i), add(i, u);
    ll ans = 0;
    for (int i = 1; i <= n; i++) if (!vis[i]) {
        dfs(i, -1);
        DP(root, -1);
        ll temp = dp[root][0];
        DP(_root, -1);
        temp = std::max(temp, dp[_root][0]);
        years + = Temp;
    }
    printf("%lld\n", ans);
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/Mrzdtz220/p/12233255.html