bozj1040: [ZJOI2008] Knight (odd ring tree, DP)

topic:

1040: [ZJOI2008] Knight

Resolution:

Assume Knight \ (u \) hate Knight \ (v \) , we \ (u \) , \ (v \) between an edge even, so we get an odd ring tree (odd ring forest), since is an odd tree rings, we will first consider the ring off, set off two points Collage connection is \ (RT1 \) , \ (RT2 \) , then mark off the ring directly through this edge is not enough the

According meaning of the questions, we ask for is two adjacent nodes can not be the greatest value at the time of the election at the same time , is not that odd ring tree edition no party boss of you.

Then it is easy to obtain transfer equation
set \ (f [u] [1/0 ] \) represented by \ (U \) for the root, selected / non-selected maximum value obtainable
\ [\ begin {cases} f [u ] [1] + = f [ v] [0] \\\\ f [u] [0] + = max (f [v] [0], f [v] [1]) \ end {cases} \ ]

Respectively, then \ (RT1 \) , \ (RT2 of \) is the root of a tree do DP

Since \ (RT1 \) and \ (RT2 of \) are the two points on the ring, the two points can not be selected simultaneously, we are forced \ (RT1 \) , \ (RT2 of \) is not selected, the maximum accumulation

Original ring may be the odd forest, so use vis mark about whether or not each point is visited

Code:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e6 + 10;
 
int n, m, num = 1, rt1, rt2, flag, ans, kk;
int head[N], f[N][2], a[N];
 
bool vis[N], vis2[N];
 
struct node {
    int v, nx;
} e[N];
 
template<class T>inline void read(T &x) {
    x = 0; int f = 0; char ch = getchar();
    while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
    while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
    x = f ? -x : x;
    return;
}
 
inline void add(int u, int v) {
    e[++num] = (node) {v, head[u]}, head[u] = num;
}
 
void FindCircle(int u, int fa) {
    vis[u] = 1;
    for (int i = head[u]; ~i; i = e[i].nx) {
        int v = e[i].v;
        if (v == fa) continue;
        if (!vis[v]) FindCircle(v, u);
        else {
            rt1 = u, rt2 = v;
            kk = i;
        }
    }
}
 
void dfs(int u, int fa) {
    f[u][1] = a[u];
    for (int i = head[u]; ~i; i = e[i].nx) {
        int v = e[i].v;
        if (v == fa || i == kk || (i ^ 1) == kk) continue;
        dfs(v, u);
        f[u][1] += f[v][0];
        f[u][0] += max(f[v][1], f[v][0]);
    }
}
 
signed main() {
    memset(head, -1, sizeof head);
    read(n);
    for (int i = 1, x; i <= n; ++i) {
        read(a[i]), read(x);
        add(i, x), add(x, i);
    }
    for (int i = 1; i <= n; ++i) {
        if (vis[i]) continue;
        int tmp = 0;
        FindCircle(i, -1);
        memset(f, 0, sizeof f);
        dfs(rt1, -1);
        tmp = max(tmp, f[rt1][0]);
        memset(f, 0, sizeof f);
        dfs(rt2, -1);
        tmp = max(tmp, f[rt2][0]);
        ans += tmp;
         
    }
    cout << ans << endl;
}

Guess you like

Origin www.cnblogs.com/lykkk/p/11355732.html