仙人掌。
仙人掌入门题。。不过入门都好难。。。
题解好复杂。。
总体来说,没有环的话,就是一棵树,很好求。
如果有环的话,就找出这个环,用一个单调队列用环上俩个点对更新答案。(如果不用单调队列就O(n^2)超时)
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 3000000 + 10; int g[maxn],v[maxn],next[maxn],eid; int p[maxn],w[maxn],dis[maxn]; int low[maxn],dfn[maxn],fa[maxn]; int ring[maxn],cnt; int n,m,res; void addedge(int a,int b) { v[eid]=b; next[eid]=g[a]; g[a]=eid++; v[eid]=a; next[eid]=g[b]; g[b]=eid++; } void getring() { int l=1,r=1; for(int i=1;i<=cnt;i++) ring[i+cnt]=ring[i]; for(int i=1;i<=(cnt<<1);i++) { while(l<r && i-p[l]>(cnt>>1)) l++; while(l<r && w[r]<=dis[ring[i]]-i) r--; ++r; p[r]=i; w[r]=dis[ring[i]]-i; res=max(res,dis[ring[i]]+i+w[l]); } } void dfs(int u) { low[u]=dfn[u]; for(int i=g[u];~i;i=next[i]) if(fa[v[i]] && v[i] !=fa[u]) low[u]=min(low[u],dfn[v[i]]); else if(!fa[v[i]]) { fa[v[i]]=u; dfn[v[i]]=dfn[u]+1; dfs(v[i]); low[u]=min(low[u],low[v[i]]); } for(int i=g[u];~i;i=next[i]) { if(fa[v[i]]==u && low[v[i]]>dfn[u]) { res=max(res,dis[v[i]]+1+dis[u]); dis[u]=max(dis[u],dis[v[i]]+1); } if(fa[v[i]]!=u && dfn[u]<dfn[v[i]]) { int p=v[i]; cnt=0; while(p!=fa[u]) { ring[++cnt]=p; p=fa[p]; } getring(); for(int j=1;j<cnt;j++) dis[u]=max(dis[u],dis[ring[j]]+min(j,cnt-j)); } } } int main() { memset(g,-1,sizeof(g)); scanf("%d%d",&n,&m); for(int i=1,a,b,x;i<=m;i++) { scanf("%d%d",&x,&a); for(int j=2;j<=x;j++) { scanf("%d",&b); addedge(a,b); a=b; } } fa[1]=-1; dfs(1); printf("%d ",res); return 0; }