bzoj1023

时间:2023-03-08 17:29:25

研究了一下仙人掌
首先,仙人掌虽然不是树,但却有很强的树的既视感
如果把每个环都看做一个点,那么他就是一棵树
当然这不能直接缩环,因为环和环可以有一个交点
如果是树,求直径都会做,令f[i]表示i到子树的最长距离然后弄一弄
但现在是树套环,怎么弄?
我们先根据dfs时间戳的思想,dfs下去,构成了一棵dfs树
我们的思想是先处理桥(树边),再处理环
这时候f[i]表示i在dfs树上i到子树的最长距离
dfs到i时,我们先用树形dp的思想求出不考虑环的f[i]
然后再把环拉出来一个个考虑,显然环上点j的f[j]除了和环上另一个点组成的路径对ans直接影响外
只会通过对最高点(时间戳最小的点)i的f[i]的影响来影响其他非以i为根的子树上的点
所以我们用环上的点来更新f[i]即可
再考虑环上两点路径对ans直接影响,枚举点j,显然可以得到
显然可以得到ans=max(ans,f[j]+max(f[k]+dis(j,k)));
我们对环上的点按照dfs树上的深度由小到大编号,t是环上点总数
可以得到dis(j,k)=min(k-j,t-k+j-i+1) (k>j)
考虑到环上两点间距离有两种情况,对此我们可以把环复制一遍然后做单调队列即可
最后,显然所有更新都是先更新ans再更新f[i],

 {$m 1000000}
type node=record
po,next:longint;
end; var a,q:array[..] of longint;
fa,low,dfn,f,p,d:array[..] of longint;
e:array[..] of node;
j,s,ans,h,len,i,n,m,x,y:longint; function min(a,b:longint):longint;
begin
if a>b then exit(b) else exit(a);
end; function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end; procedure add(x,y:longint);
begin
inc(len);
e[len].po:=y;
e[len].next:=p[x];
p[x]:=len;
end; procedure dp(x,y:longint);
var t,h,r,i,p:longint;
begin
t:=d[y]-d[x]+; //环上点的数目
h:=;
r:=;
p:=y;
for i:=t downto do
begin
a[i]:=f[p];
a[i+t]:=a[i]; //复制一遍,把两点间距离转化为编号差
p:=fa[p];
end;
q[]:=; //维护单调减的双端队列
for i:= to t+t div do
begin
while (h<=r) and (q[h]<i-t div ) do inc(h); //队头的点和当前点的距离已经不是最短距离
ans:=max(ans,a[q[h]]+a[i]+i-q[h]);
while (h<=r) and (a[q[r]]-q[r]<=a[i]-i) do dec(r);
inc(r);
q[r]:=i;
end;
for i:= to t do
f[x]:=max(f[x],a[i]+min(i-,t-i+));
end; procedure tarjan(x:longint);
var i,y:longint;
begin
inc(h);
dfn[x]:=h;
low[x]:=h;
i:=p[x];
while i<> do
begin
y:=e[i].po;
if fa[x]<>y then
begin
if dfn[y]= then
begin
fa[y]:=x;
d[y]:=d[x]+;
tarjan(y);
end;
low[x]:=min(low[x],low[y]);
if dfn[x]<low[y] then //如果与x和x的祖先不构成环
begin
ans:=max(ans,f[x]+f[y]+);
f[x]:=max(f[x],f[y]+);
end;
end;
i:=e[i].next;
end;
i:=p[x];
while i<> do
begin
y:=e[i].po;
if (fa[y]<>x) and (dfn[x]<dfn[y]) then //与x节点成环
dp(x,y);
i:=e[i].next;
end;
end; begin
readln(n,m);
for i:= to m do
begin
read(s);
read(x);
for j:= to s do
begin
read(y);
add(x,y);
add(y,x);
x:=y;
end;
end;
tarjan();
writeln(ans);
end.