首页 > 其他 > 详细

bzoj1023: [SHOI2008]cactus仙人掌图

时间:2018-01-07 22:45:30      阅读:203      评论:0      收藏:0      [点我收藏+]

传送门

求仙人掌的直径。

求一遍边双,建立圆方树,然后在树上dp;

技术分享图片
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<ctime>
const int N=100007; 
typedef long long LL;
using namespace std;
int n,m;

template<typename T> void read(T &x) {
    T f=1; x=0; char ch=getchar();
    while(ch!=-&&(ch<0||ch>9)) ch=getchar();
    if(ch==-) f=-1,ch=getchar();
    for(;ch>=0&&ch<=9;ch=getchar()) x=x*10+ch-0; x*=f;
}

int ecnt=1,fir[N],nxt[N<<1],to[N<<1]; 
void add(int u,int v) {
    nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
    nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u;
}

int ec,fi[N],nx[N],tt[N]; 
void add_edge(int u,int v) {
    nx[++ec]=fi[u]; fi[u]=ec; tt[ec]=v;
}

int tot,dfn[N],low[N],dfs_clock,sta[N],top;
void tarjan(int x,int f) {
    dfn[x]=low[x]=++dfs_clock;
    sta[++top]=x;
    for(int i=fir[x];i;i=nxt[i]) {
        int y=to[i];
        if(!dfn[y]) {
            tarjan(y,i^1);
            if(low[y]>dfn[x]) add_edge(x,y),top--;  
            low[x]=min(low[x],low[y]);
            if(low[y]==dfn[x]) {
                add_edge(x,++tot);
                while(top) {
                    int z=sta[top--];
                    add_edge(tot,z);
                    if(z==y) break;
                }
            }
        }
        else if(i^f) low[x]=min(low[x],dfn[y]);
    }
}

int f[N],que[N],ql,qr,tmp[N],tp,ans;
void dfs(int x) {
    for(int i=fi[x];i;i=nx[i]) 
        dfs(tt[i]);
    if(x<=n) {
        int cd=0;
        for(int i=fi[x];i;i=nx[i]) {
            cd=max(cd,f[tt[i]]+1);
            if(cd>f[x]) swap(cd,f[x]);
        }
        ans=max(ans,f[x]+cd); 
    }
    else {
        ql=1; qr=0; tp=1;
        for(int i=fi[x];i;i=nx[i]) tmp[tp++]=tt[i];
        for(int i=0;i<tp;i++) tmp[tp+i]=tmp[i];
        for(int i=1;i<=(tp>>1)+tp;i++) {
            while(ql<=qr&&(i-que[ql])*2>tp) ql++;
            if(i>(tp>>1)) ans=max(ans,f[tmp[i]]+f[tmp[que[ql]]]+i-que[ql]);
            while(ql<=qr&&f[tmp[que[qr]]]-que[qr]<=f[tmp[i]]-i) qr--;
            que[++qr]=i;
        }
        for(int i=1;i<=(tp>>1);i++) f[x]=max(f[x],f[tmp[i]]+i-1);
        for(int i=(tp>>1)+1;i<tp;i++) f[x]=max(f[x],f[tmp[i]]+tp-i-1);
    }
}

int main() {
    read(n); read(m); tot=n;
    while(m--) {
        int k,x,y;
        read(k); read(x);
        for(int i=k-1;i;i--) {
            read(y); add(x,y); x=y; 
        }
    }
    for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,0);
    dfs(1);
    printf("%d\n",ans); 
    return 0;
}
/*
15 3
9 1 2 3 4 5 6 7 8 3
7 2 9 10 11 12 13 10 
5 2 14 9 15 10    8
10 1
10 1 2 3 4 5 6 7 8 9 10
*/
View Code

 

bzoj1023: [SHOI2008]cactus仙人掌图

原文:https://www.cnblogs.com/Achenchen/p/8231087.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!