BZOJ1023: [SHOI2008]cactus仙人掌图
题意:求一棵仙人掌图的直径。
题解:戳ydc
http://ydcydcy1.blog.163.com/blog/static/21608904020131493113160/
代码:
int n,m,tot,head[maxn],dep[maxn],a[maxn],fa[maxn],q[maxn],low[maxn],dfn[maxn],f[maxn],ans; struct edge{int go,next;}e[2*maxn]; inline void add(int x,int y) { e[++tot]=(edge){y,head[x]};head[x]=tot; e[++tot]=(edge){x,head[y]};head[y]=tot; } inline void dp(int rt,int x) { int k=dep[x]-dep[rt]+1; for1(i,k)a[i]=a[k+i]=x,x=fa[x]; int l=1,r=0;q[1]=0; for1(i,k<<1) { while(l<=r&&i-q[l]>k>>1)l++; ans=max(ans,f[a[q[l]]]+f[a[i]]+i-q[l]); while(l<=r&&f[a[q[r]]]-q[r]<=f[a[i]]-i)r--; q[++r]=i; } for1(i,k-1)f[rt]=max(f[rt],f[a[i]]+min(k-i,i)); } inline void dfs(int x) { dfn[x]=low[x]=++m; for4(i,x)if(y!=fa[x]) { if(!dfn[y]){fa[y]=x;dep[y]=dep[x]+1;dfs(y);low[x]=min(low[x],low[y]);} else low[x]=min(low[x],dfn[y]); if(dfn[x]<low[y]) { ans=max(ans,f[x]+f[y]+1); f[x]=max(f[x],f[y]+1); } } for4(i,x)if(fa[y]!=x&&dfn[x]<dfn[y])dp(x,y); } int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); n=read();m=read(); for1(i,m) { int k=read(),x=read(),y; for1(i,k-1)y=read(),add(x,y),x=y; } m=0; dfs(1); cout<<ans<<endl; return 0; }