题面
http://darkbzoj.tk/problem/1023
- 仙人掌上建有根圆方树(对于方点维护$son[x][i]$和$len[x][i]$,改变$len[x][i]$的定义以规避讨论)
- 单调队列维护加入元素和查找最大值的操作。
- 其他思路大体上和最短路(http://darkbzoj.tk/problem/2125)一样。
#include<cstdio> #include<cstring> #include<iostream> #include<stack> #include<vector> #define ri register int #define N 100500 using namespace std; int n,tn,m; int cir[N]; int a[N]; int ans; inline int read() { int ret=0,f=0; char ch=getchar(); while (ch<'0' || ch>'9') f|=(ch=='-'),ch=getchar(); while (ch>='0'&&ch<='9') ret*=10,ret+=ch-'0',ch=getchar(); return f?-ret:ret; } struct tree { vector<int> son[N],len[N]; int f[N]; void add_edge(int a,int b,int c) { son[b].push_back(a); len[b].push_back(c); } void dp(int x) { if (!son[x].size()) { f[x]=0; return; } for (ri i=0;i<son[x].size();i++) dp(son[x][i]); if (x<=tn) { f[x]=-1; int p=-1; for (ri i=0;i<son[x].size();i++) if (f[son[x][i]]>f[x]) f[x]=f[son[x][i]],p=son[x][i]; if (f[x]>ans) ans=f[x]; for (ri i=0;i<son[x].size();i++) if (son[x][i]!=p) if (f[x]+f[son[x][i]]>ans) ans=f[x]+f[son[x][i]]; } else { f[x]=0; int l=son[x].size(); for (ri i=0;i<l;i++) { if (min(cir[x]-len[x][i],len[x][i])+f[son[x][i]]>f[x]) f[x]=min(cir[x]-len[x][i],len[x][i])+f[son[x][i]]; son[x].push_back(son[x][i]); len[x].push_back(cir[x]+len[x][i]); } deque<int> q; while (!q.empty()) q.pop_back(); for (ri i=0;i<son[x].size();i++) { int a=son[x][i],dis=len[x][i]; while (q.size() && 2*(dis-len[x][q.back()])>cir[x]) q.pop_back(); if (q.size() && f[a]+f[son[x][q.back()]]+dis-len[x][q.back()]>ans) ans=f[a]+f[son[x][q.back()]]+dis-len[x][q.back()]; while (q.size() && f[a]-dis>f[son[x][q.front()]]-len[x][q.front()]) q.pop_front(); q.push_front(i); } } } } T; struct graph { vector<int> to[N]; int dfn[N],low[N],cnt; int pre[N],dr[N]; stack<int> s; void add_edge(int a,int b) { to[a].push_back(b); to[b].push_back(a); } void tarjan(int x) { dfn[x]=low[x]=++cnt; s.push(x); for (ri i=0;i<to[x].size();i++) { int y=to[x][i]; if (dfn[y]) low[x]=min(low[x],dfn[y]); else { pre[y]=x; dr[y]=dr[x]+1; tarjan(y); if (low[y]>=dfn[x]) { ++n; cir[n]=dr[s.top()]-dr[x]+1; T.add_edge(n,x,0); int t; do { t=s.top(); s.pop(); T.add_edge(t,n,cir[n]-dr[t]+dr[x]); } while (t!=y); } low[x]=min(low[x],low[y]); } } } } G; int main() { tn=n=read(); m=read(); for (ri i=1;i<=m;i++) { int k=read(); for (ri j=1;j<=k;j++) a[j]=read(); for (ri j=2;j<=k;j++) G.add_edge(a[j-1],a[j]); } G.cnt=0; G.tarjan(1); T.dp(1); printf("%d ",ans); }