[ZJOI2008]骑士
看题时像一个独立集的题,看了数据之后。。。。
主要在于:每个骑士都有且仅有一个自己最厌恶的骑士。
所以整个图是多个联通块,每联通块都是一个环和一些树。
先在树上做dp,
可以枚举环上两点,分别不取。
也可以写个环dp。
(我写的是环dp)
/**
* Problem:[ZJOI2008]p5
* Author:Shun Yao
* Time:2013.5.30
* Result:Accepted
* Memo:DP
*/
#include <cstring>
#include <cstdio>
const long Maxn = 1000005;
long long max(long long x, long long y) {
return x > y ? x : y;
}
void swap(long &x, long &y) {
x ^= y;
y ^= x;
x ^= y;
}
long n, A[Maxn], fa[Maxn], ff[Maxn];
long long ans, f[Maxn][2];
class gnode {
public:
long v;
gnode *next;
gnode() {}
~gnode() {}
gnode(long V, gnode *ne):v(V), next(ne) {}
} *g[Maxn];
void add(long x, long y) {
g[x] = new gnode(y, g[x]);
g[y] = new gnode(x, g[y]);
}
void DP_Tree(long x) {
static long q[Maxn], *l, *r;
static gnode *e;
r = (l = &(*q = x)) + 1;
while (l != r) {
for (e = g[*l]; e; e = e->next) if (!ff[e->v]) {
ff[e->v] = *l;
*(r++) = e->v;
}
++l;
}
do {
--l;
f[*l][0] = 0;
f[*l][1] = A[*l];
for (e = g[*l]; e; e = e->next) if (ff[e->v] == *l) {
f[*l][0] += f[e->v][1];
f[*l][1] += f[e->v][0];
}
f[*l][1] = max(f[*l][1], f[*l][0]);
} while (l != q);
}
long q[Maxn], *l, *r;
long st[Maxn << 1], stl;
long ST[Maxn], STl;
long d[Maxn];
long long h[Maxn];
void DP(long x) {
static gnode *e;
static long a, b;
r = (l = &(*q = x)) + 1;
fa[x] = -1;
stl = 0;
STl = 0;
while (l != r) {
for (e = g[*l]; e; e = e->next) if (e->v != fa[*l]) {
if (!fa[e->v]) {
d[e->v] = d[*l] + 1;
fa[e->v] = *l;
*(r++) = e->v;
} else if (!stl) {
a = *l;
b = e->v;
if (d[a] < d[b])
swap(a, b);
while (d[a] > d[b]) {
st[++stl] = a;
a = fa[a];
}
while (a != b) {
st[++stl] = a;
ST[++STl] = b;
a = fa[a];
b = fa[b];
}
st[++stl] = a;
while (STl)
st[++stl] = ST[STl--];
}
}
++l;
}
static long i;
for (i = 1; i <= stl; ++i)
ff[st[i]] = -1;
for (i = 1; i <= stl; ++i)
DP_Tree(st[i]);
static long long ret;
h[0] = 0;
h[1] = f[st[1]][1];
for (i = 2; i < stl; ++i)
h[i] = max(h[i - 2] + f[st[i - 1]][0] + f[st[i]][1], h[i - 1] + f[st[i]][0]);
ret = h[stl - 1] + f[st[stl]][0];
h[1] = 0;
h[2] = f[st[2]][1];
for (i = 3; i <= stl; ++i)
h[i] = max(h[i - 2] + f[st[i - 1]][0] + f[st[i]][1], h[i - 1] + f[st[i]][0]);
ans += max(h[stl] + f[st[1]][0], ret);
}
int main() {
static long i, B;
freopen("p5.in", "r", stdin);
freopen("p5.out", "w", stdout);
scanf("%ld", &n);
for (i = 1; i <= n; ++i)
g[i] = 0;
for (i = 1; i <= n; ++i) {
scanf("%ld%ld", A + i, &B);
add(i, B);
}
memset(d, 0, sizeof d);
memset(fa, 0, sizeof fa);
memset(ff, 0, sizeof ff);
ans = 0;
for (i = 1; i <= n; ++i)
if (!fa[i])
DP(i);
printf("%lld", ans);
fclose(stdin);
fclose(stdout);
return 0;
}
作者:HSUPPR
出处:http://www.cnblogs.com/hsuppr/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出
原文链接,否则保留追究法律责任的权利。

浙公网安备 33010602011771号