[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/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出
原文链接,否则保留追究法律责任的权利。