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


    良心的题解↓

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

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

    总复杂度$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
    ", ans);
    	return 0;
    }
    

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

  • 相关阅读:
    2016/11/2
    2016/11/1
    bzoj 3809: Gty的二逼妹子序列
    bzoj 1207: [HNOI2004]打鼹鼠
    bzoj 1191: [HNOI2006]超级英雄Hero
    BZOJ 1854: [Scoi2010]游戏
    BZOJ 1296: [SCOI2009]粉刷匠
    BZOJ 1787: [Ahoi2008]Meet 紧急集合
    tarjan算法
    高级的暴力(一)——分块
  • 原文地址:https://www.cnblogs.com/abclzr/p/5506534.html
Copyright © 2020-2023  润新知