Title Link: BZOJ-1040
Problem analysis
The model of this problem is a graph, not necessarily connected, each connecting block points equal to the number of sides.
Each connected block is a base ring + outward tree. An edge is added to the tree.
If it is a tree, it can be directly tree-shaped DP. However, this is the base ring + outward tree, you need to find an edge on the ring, record the edge of the two endpoints R1, R2, delete this edge.
Then in two cases: certainly do not choose R1, must not choose R2; do a tree DP on each of these two cases.
The answer adds to the larger value of the answer to both cases.
Code
#include <iostream> #include <cstdlib> #include <cstring> #include <cmath> #include < Algorithm> #include <cstdio>using namespace std;const int maxn = 1000000 + 5;typedef long long ll;const LL INF = 9 9999999999999999;int N, R, R1, R2, Rt;int A[MAXN]; LL Ans, Temp; LL F[maxn][2];bool visit[maxn];struct edge{int u, V, t; Edge *next;} E[MAXN * 2], *p = E, *point[maxn];inline void Addedge (int x, int y, int z) {++p; P-u = x; P-v = y; P-T = z; P-Next = point[x]; POINT[X] = P;} inline ll Gmax (ll A, ll b) {return a > b a:b;} void DFS (int x, int y) {visit[x] = true;for (Edge *j = point[x]; j; j = J-Next) {if (J-t = = y) continue;if (Vi Sit[j v]) {R1 = x; R2 = J V; Rt = J-T;} Else DFS (J-V, J-T);}} void Solve (int x, int y) {f[x][0] = 0; F[X][1] = a[x];for (Edge *j = point[x]; j; j = J-Next) {if (J-t = = y | | J, T = = Rt) continue; Solve (J-V, J-T); F[x][0] + = Gmax (F[j-v][0], f[J-V][1]); F[X][1] + = f[j-v][0]; }if (x = = R) f[x][1] =-inf;} int main () {scanf ("%d", &n), int a;for (int i = 1; I <= n; ++i) {scanf ("%d%d", &a[i], &a); Addedge (i, A, i); Addedge (A, I, I);} memset (Visit, 0, sizeof (Visit)); Ans = 0;for (int i = 1; I <= n; ++i) {if (Visit[i]) Continue;dfs (i, 0); R = R1; Solve (i, 0); Temp = Gmax (F[i][0], f[i][1]); R = R2; Solve (i, 0); temp = Gmax (temp, Gmax (f[i][0], f[i][1])); Ans + = Temp;} printf ("%lld\n", Ans); return 0;}
[Bzoj 1040] [ZJOI2008] Knight "base ring + Outward tree DP"