【BZOJ1023】仙人掌圖(仙人掌,動態規劃)
阿新 • • 發佈:2018-05-26
轉移 tps 同時 HR code main 最大值 mes vector
而\(dist(i,j)=min(abs(dep[i]-dep[j]),circle\_size-abs(dep[i]-dep[j]))\)
發現維護一個單調隊列,按照深度依次進棧,
這樣子距離直接可以用深度做差,沒有了絕對值
因為可以通過返祖邊回去,因此把所有點按照順序進兩次隊就可以了
第二次進隊的時候給深度加上一個環大小再進隊
然後如何保證是環上的最短路?
如果兩個深度差已經大於環大小的一半了,那麽最短路就不是這一條了
所以直接彈走隊首就行了
【BZOJ1023】仙人掌圖(仙人掌,動態規劃)
題面
BZOJ
求仙人掌的直徑(兩點之間最短路徑最大值)
題解
一開始看錯題了,以為是求仙人掌中的最長路徑。。。
後來發現看錯題了一下就改過來了。。
首先和普通的仙人掌\(dp\)是一樣的,
對於沒有問題的圓圓邊,直接做最長鏈的轉移(同時更新\(ans\))
然後對於一個環,把它拎出來單獨考慮
首先要對於這個環,計算能夠貢獻的答案,
然後再用環上的值更新環的最頂點
先考慮怎麽更新,這個直接拿環上的點的\(dp\)值,再計算一下這兩點之間的最短路(深度差和環大小減深度差的較小值),相加去更新\(dp\)值。
然後考慮一下如何貢獻答案,
要求的相當於是\(max(f[i]+f[j]+dist(i,j))\)
而\(dist(i,j)=min(abs(dep[i]-dep[j]),circle\_size-abs(dep[i]-dep[j]))\)
發現維護一個單調隊列,按照深度依次進棧,
這樣子距離直接可以用深度做差,沒有了絕對值
因為可以通過返祖邊回去,因此把所有點按照順序進兩次隊就可以了
第二次進隊的時候給深度加上一個環大小再進隊
然後如何保證是環上的最短路?
如果兩個深度差已經大於環大小的一半了,那麽最短路就不是這一條了
所以直接彈走隊首就行了
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 55555
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0' ||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
struct Line{int v,next;}e[MAX<<3];
int h[MAX],cnt=1,n,m;
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
int f[MAX],ans=1,fa[MAX],dep[MAX],dfn[MAX],low[MAX],tim;
int H,T,Q1[MAX<<1],Q[MAX<<1];
void dp(int u,int y)
{
int t=0;
for(int i=y;i!=u;i=fa[i])Q1[++t]=i;Q1[++t]=u;
reverse(&Q1[1],&Q1[t+1]);
for(int i=1;i<=t;++i)Q1[i+t]=Q1[i];
H=1;T=0;
for(int i=1;i<=t+t;++i)
{
while(H<=T&&i-Q[H]>t/2)++H;
if(H<=T)ans=max(ans,f[Q1[i]]+f[Q1[Q[H]]]+i-Q[H]);
while(H<=T&&f[Q1[i]]-i>f[Q1[Q[T]]]-Q[T])--T;
Q[++T]=i;
}
for(int i=y;i!=u;i=fa[i])
f[u]=max(f[u],f[i]+min(dep[i]-dep[u],1+dep[y]-dep[i]));
}
void dfs(int u,int ff)
{
fa[u]=ff;dfn[u]=low[u]=++tim;dep[u]=dep[ff]+1;
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;
if(!dfn[v])dfs(v,u),low[u]=min(low[u],low[v]);
else if(v!=ff)low[u]=min(low[u],dfn[v]);
if(low[v]>dfn[u])
ans=max(ans,f[u]+f[v]+1),f[u]=max(f[u],f[v]+1);
}
for(int i=h[u];i;i=e[i].next)
if(fa[e[i].v]!=u&&dfn[u]<dfn[e[i].v])
dp(u,e[i].v);
}
int main()
{
n=read();m=read();
for(int i=1;i<=m;++i)
{
int K=read(),a=read();
for(int j=1;j<K;++j)
{
int b=read();
Add(a,b);Add(b,a);
a=b;
}
}
dfs(1,0);
printf("%d\n",ans);
return 0;
}
【BZOJ1023】仙人掌圖(仙人掌,動態規劃)