# BZOJ1040: [ZJOI2008]骑士(奇环树,DP)

## 题目：

1040: [ZJOI2008]骑士

## 解析：

$f[u][1/0]$表示以$u$为根，选/不选可以得到的最大价值

$\begin{cases} f[u][1] += f[v][0]\\\\ f[u][0] += max(f[v][0], f[v][1]) \end{cases}$

## 代码：

#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;

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) {
}

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() {
for (int i = 1, x; i <= n; ++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;
}

posted @ 2019-08-15 07:36  Chrety  阅读(171)  评论(0编辑  收藏  举报