BZOJ 1023 [SHOI2008]cactus仙人掌图 DP+单调队列
这题不能用普通的tarjan来缩点,因为看第一个样例普通tarjan会跪的很惨。。
然后乱yy一个缩点就好了。
桥边和环上的边分开处理,挺容易看懂的。。。
神犇都说这题水,我这弱菜觉得一点都不水,,,
View Code
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <algorithm> 6 7 #define N 2222222 8 9 using namespace std; 10 11 int head[N],to[N],next[N]; 12 int n,m,cnt,tot,ans; 13 int dis[N],cir[N]; 14 int low[N],dfn[N],fa[N],tim; 15 16 struct Q 17 { 18 int p,w; 19 }q[N]; 20 21 inline void add(int u,int v) 22 { 23 to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++; 24 } 25 26 inline void read() 27 { 28 memset(head,-1,sizeof head); 29 scanf("%d%d",&n,&m); 30 for(int i=1,a,b,c;i<=m;i++) 31 { 32 scanf("%d%d",&a,&b); 33 for(int j=2;j<=a;j++) 34 { 35 scanf("%d",&c); 36 add(b,c); add(c,b); b=c; 37 } 38 } 39 } 40 41 inline void getcir() 42 { 43 int h=1,t=1; 44 for(int i=1;i<=tot;i++) cir[tot+i]=cir[i]; 45 for(int i=1;i<=(tot<<1);i++) 46 { 47 while(h<t&&i-q[h].p>(tot>>1)) h++; 48 while(h<t&&q[t].w<=dis[cir[i]]-i) t--; 49 q[++t].p=i; q[t].w=dis[cir[i]]-i; 50 ans=max(ans,dis[cir[i]]+i+q[h].w); 51 } 52 } 53 54 inline void dfs(int u) 55 { 56 low[u]=dfn[u]; 57 for(int i=head[u];~i;i=next[i]) 58 { 59 if(fa[to[i]]!=0&&to[i]!=fa[u]) low[u]=min(low[u],dfn[to[i]]); 60 if(fa[to[i]]==0) 61 { 62 fa[to[i]]=u; dfn[to[i]]=dfn[u]+1; dfs(to[i]); 63 low[u]=min(low[u],low[to[i]]); 64 } 65 } 66 for(int i=head[u];~i;i=next[i]) 67 { 68 if(fa[to[i]]==u&&low[to[i]]>dfn[u])//bridge 69 { 70 ans=max(ans,dis[to[i]]+1+dis[u]); 71 dis[u]=max(dis[u],dis[to[i]]+1); 72 } 73 if(fa[to[i]]!=u&&dfn[u]<dfn[to[i]])//circle 74 { 75 int x=to[i]; tot=0; 76 while(x!=fa[u]) cir[++tot]=x,x=fa[x]; 77 getcir(); 78 for(int j=1;j<tot;j++) dis[u]=max(dis[u],dis[cir[j]]+min(j,tot-j)); 79 } 80 } 81 } 82 83 inline void go() 84 { 85 fa[1]=-1; 86 dfs(1); 87 cout<<ans<<endl; 88 } 89 90 int main() 91 { 92 read(),go(); 93 return 0; 94 }
没有人能阻止我前进的步伐,除了我自己!