码迷,mamicode.com
首页 > 其他好文 > 详细

【BZOJ 1023】【SHOI 2008】cactus仙人掌图

时间:2016-05-18 21:54:46      阅读:241      评论:0      收藏:0      [点我收藏+]

标签:

良心的题解↓

http://z55250825.blog.163.com/blog/static/150230809201412793151890/

tarjan的时候如果是树边则做树形DP(遇到环就无视),最后在tarjan回溯前扫一遍当前点为“最高点”的环,进行环上DP,这个环上DP是$O(n^2)$的,但如果我们用单调队列优化则是$O(n×2)$的

总复杂度$O(n)$真是无限仰膜OTZ

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 500003;
void read(int &k) {
	k = 0; int fh = 1; char c = getchar();
	for(; c < ‘0‘ || c > ‘9‘; c = getchar())
		if (c == ‘-‘) fh = -1;
	for(; c >= ‘0‘ && c <= ‘9‘; c = getchar())
		k = (k << 1) + (k << 3) + c - ‘0‘;
	k = k * fh;
}

struct node {int nxt, to;} E[N << 1];
int ans = 0, point[N], n, m, cnt = 0, l, r;
int deep[N], F[N], fa[N], DFN[N], low[N], Q[N << 1], tb[N << 1];

void ins(int x, int y) {E[++cnt] = (node) {point[x], y}; point[x] = cnt;}

void __(int rt, int x) {
	int tot = deep[x] - deep[rt] + 1, num = tot << 1, top = tot >> 1;
	for(int tmp = x; tmp != rt; tmp = fa[tmp]) tb[tot--] = F[tmp];
	tb[1] = F[rt];
	tot = deep[x] - deep[rt] + 1;
	for(int i = 1; i <= tot; ++i) tb[tot + i] = tb[i];
	l = r = 1; Q[1] = 1;
	for(int i = 2; i <= num; ++i) {
		while (l <= r && i - Q[l] > top) ++l;
		ans = max(ans, tb[i] + i + tb[Q[l]] - Q[l]);
		while (l <= r && tb[Q[r]] - Q[r] <= tb[i] - i) --r;
		Q[++r] = i;
	}
	for(int i = 2; i <= tot; ++i)
		F[rt] = max(F[rt], tb[i] + min(i - 1, tot - i + 1));
}

void _(int x) {
	DFN[x] = low[x] = ++cnt;
	for(int tmp = point[x]; tmp; tmp = E[tmp].nxt) {
		int v = E[tmp].to;
		if (v == fa[x]) continue;
		if (!DFN[v]) {
			fa[v] = x; deep[v] = deep[x] + 1;
			_(v); low[x] = min(low[x], low[v]);
		} else
			low[x] = min(low[x], DFN[v]);
		if (DFN[x] < low[v]) {
			ans = max(ans, F[x] + F[v] + 1);
			F[x] = max(F[x], F[v] + 1);
		}
	}
	for(int tmp = point[x]; tmp; tmp = E[tmp].nxt) {
		int v = E[tmp].to;
		if (x == fa[v] || DFN[x] > DFN[v]) continue;
		__(x, v);
	}
}

int main() {
	read(n); read(m);
	
	int u, v, k;
	for(int i = 1; i <= m; ++i) {
		read(k); read(u);
		for(--k; k; --k) {read(v); ins(u, v); ins(v, u); u = v;}
	}
	
	cnt = 0;
	_(1);
	printf("%d\n", ans);
	return 0;
}

仙人掌虽然偏,但是不知道也不可以,这个代码是我磕了一晚上题解的成果QAQ

【BZOJ 1023】【SHOI 2008】cactus仙人掌图

标签:

原文地址:http://www.cnblogs.com/abclzr/p/5506534.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!