BZOJ1017 [JSOI2008]魔兽地图DotR
BZOJ2342 [Shoi2011]双倍回文

BZOJ1040 [ZJOI2008]骑士

laekov posted @ 2015年2月23日 11:48 in 未分类 with tags bzoj dp , 478 阅读

多少年前的坑了。

 

用mac写的第一篇题解呢。

 

环套树DP。先把树上的情况处理了,然后枚举取不取环上的第一个。

 

要注意会有重边的情况,比较恶心。

 

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>

using namespace std;

const int buf_len = 4000;
char buf[buf_len], *bufb(buf), *bufe(buf + 1);
#define readBuf() { \
	if (++ bufb == bufe) \
		bufe = (bufb = buf) + fread(buf, 1, sizeof(buf), stdin); \
}
#define readInt(_x_) { \
	register int _s_(0); \
	do { \
		readBuf(); \
	} while (!isdigit(*bufb)); \
	do { \
		_s_ = _s_ * 10 + *bufb - 48; \
		readBuf(); \
	} while (isdigit(*bufb)); \
	_x_ = _s_; \
}

typedef long long dint;
#ifdef WIN32
#define lld "%I64d"
#else
#define lld "%lld"
#endif

struct edge {
	int t;
	edge *next;
};

const int maxn = 1000009;

int n, v[maxn];
int stc[maxn], tst, lpp[maxn], tlp;
int vis[maxn], onl[maxn];
dint f[maxn], g[maxn];
edge elst[maxn << 1], *ep(elst), *head[maxn];

inline void addEdge(int u, int v) {
	ep-> t = v;
	ep-> next = head[u];
	head[u] = ep ++;
}

void dfsLoop(int p, int fr) {
	vis[p] = fr + 1;
	stc[tst ++] = p;
	for (edge* e = head[p]; e; e = e-> next)
		if (e-> t != fr) {
			if (!vis[e-> t]) {
				dfsLoop(e-> t, p);
			}
			else if (vis[e-> t] && vis[e-> t] != p + 1) {
				if (onl[p])
					continue;
				tlp = 0;
				do {
					-- tst;
					lpp[tlp ++] = stc[tst];
					onl[stc[tst]] = 1;
				} while (stc[tst] != e-> t);
			}
		}
	if (stc[tst - 1] == p)
		-- tst;
}

void dfsDP(int p, int fr) {
	f[p] = 0;
	g[p] = v[p];
	vis[p] = -1;
	for (edge* e = head[p]; e; e = e-> next)
		if (e-> t != fr && !onl[e-> t] && vis[e-> t] != -1) {
			dfsDP(e-> t, p);
			f[p] += max(f[e-> t], g[e-> t]);
			g[p] += f[e-> t];
		}
}

dint calcCC(int p) {
	tst = 0;
	tlp = 0;
	dfsLoop(p, 0);
	if (!tlp)
		lpp[tlp ++] = p;
	for (int i = 0; i < tlp; ++ i)
		dfsDP(lpp[i], 0);
	dint s0(0), s1(0);
	if (tlp < 3) {
		for (int i = 0; i < tlp; ++ i)
			s0 = max(s0, g[lpp[i]] - f[lpp[i]]);
		for (int i = 0; i < tlp; ++ i)
			s0 += f[lpp[i]];
	}
	else {
		dint f0(g[lpp[0]] + f[lpp[1]] + f[lpp[tlp - 1]]), g0(f0);
		for (int i = 2; i < tlp - 1; ++ i) {
			dint f1(f[lpp[i]] + max(f0, g0)), g1(g[lpp[i]] + f0);
			f0 = f1;
			g0 = g1;
		}
		s0 = max(f0, g0);
	}
	if (tlp < 3) {
		s1 = s0;
	}
	else {
		dint f0(f[lpp[0]]), g0(f0);
		for (int i = 1; i < tlp; ++ i) {
			dint f1(f[lpp[i]] + max(f0, g0)), g1(g[lpp[i]] + f0);
			f0 = f1;
			g0 = g1;
		}
		s1 = max(g0, f0);
	}
	return max(s0, s1);
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
#endif

	readInt(n);
	memset(head, 0, sizeof(head));
	for (int i = 1; i <= n; ++ i) {
		int x;
		readInt(v[i]);
		readInt(x);
		addEdge(i, x);
		addEdge(x, i);
	}
	memset(vis, 0, sizeof(vis));
	memset(onl, 0, sizeof(onl));
	dint ans(0);
	for (int i = 1; i <= n; ++ i)
		if (!vis[i])
			ans += calcCC(i);
	printf(lld "\n", ans);
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter