1 条题解
-
0
首先树上 距离 那么可以相向移动,所以只要暴力枚举距离 的点对。
对于基环树上的问题,类似地如果 都不在环上,则只要考虑距离 的情况。
否则我们只要考虑存在一个不完全同色的环的情况。
枚举该环,必定有一个点在环上,设为 ,则分讨环上是否有黑色点。
如果有,则粉点和黑点都是区间,且两个区间中间夹了 个蓝色点。
枚举粉色区间后只有 种要检验的区间对,我们要在长度较小的区间上任意一个点的子树中找到深度为 区间长度差的点。
那么换根 dp 求仙人掌上每个点子树内外最大深度,然后单调队列维护区间最深点即可判断。
如果没有黑点,则蓝点和黑点都是区间,且粉点一定是蓝点区间两个端点的某个子树,枚举该子树并算出黑点范围,然后要在该子树中找深度为某个值的点,依然可以预处理。
时间复杂度 。
代码:
#include<bits/stdc++.h> #define ll long long using namespace std; const int MAXN=4e5+5; vector <int> G[MAXN],E[MAXN]; int n,m,vc,A,B,dfn[MAXN],low[MAXN],dcnt,st[MAXN],tp; bool ins[MAXN]; void tarjan(int u) { dfn[u]=low[u]=++dcnt,ins[st[++tp]=u]=1; for(int v:E[u]) { if(!dfn[v]) { tarjan(v),low[u]=min(low[u],low[v]); if(low[v]>=dfn[u]) { for(G[u].push_back(++vc);ins[v];ins[st[tp--]]=0) G[vc].push_back(st[tp]); } } else low[u]=min(low[u],dfn[v]); } } int siz[MAXN],fa[MAXN],c[MAXN],f[MAXN]; void dfs1(int u,int fz) { siz[u]=u<=n,fa[u]=fz; for(int v:G[u]) dfs1(v,u),siz[u]+=siz[v]; if(u<=n) for(int v:G[u]) f[u]=max(f[u],f[v]); else { c[u]=G[u].size()+1; for(int i=0;i<c[u]-1;++i) f[u]=max(f[u],f[G[u][i]]+min(i+1,c[u]-1-i)); } } int g[MAXN],q[MAXN],w[MAXN]; void dfs2(int u) { if(u<=n) { int fi=g[u],se=0; for(int v:G[u]) se=max(se,min(fi,f[v])),fi=max(fi,f[v]); for(int v:G[u]) g[v]=(f[v]==fi?se:fi); } else { w[c[u]-1]=g[u]; for(int i=0;i<c[u]-1;++i) w[i]=w[i+c[u]]=f[G[u][i]]; int hd=1,tl=0,d=c[u]/2; for(int o=2;o--;) { for(int i=0;i<2*c[u]-1;++i) { while(hd<=tl&&q[hd]<i-d) ++hd; if(i>=c[u]) g[G[u][i-c[u]]]=max(g[G[u][i-c[u]]],i-q[hd]+w[q[hd]]); while(hd<=tl&&w[q[tl]]-q[tl]<=w[i]-i) --tl; q[++tl]=i; } reverse(w,w+2*c[u]-1),reverse(G[u].begin(),G[u].end()); } } for(int v:G[u]) dfs2(v); } vector <int> H[MAXN]; int d[MAXN],b[MAXN],pa[MAXN],pb[MAXN],xa[MAXN],xb[MAXN]; ll s[MAXN]; bool vis[MAXN]; int in(int x,int e) { queue <array<int,2>> Q; Q.push({x,0}); while(1) { auto u=Q.front(); Q.pop(); if(u[1]==e) return u[0]; for(int v:E[u[0]]) if(!vis[v]) vis[v]=true,Q.push({v,u[1]+1}); } } void solve() { cin>>n>>m>>A>>B,vc=n; for(int i=1,u,v;i<=m;++i) cin>>u>>v,E[u].push_back(v),E[v].push_back(u); tarjan(1),dfs1(1,0); for(int u=1;u<=n;++u) { if(!fa[u]||G[fa[u]].size()>1) continue; if(siz[u]==A&&n-siz[u]==B) return cout<<u<<" "<<fa[fa[u]]<<"\n",void(); if(siz[u]==B&&n-siz[u]==A) return cout<<fa[fa[u]]<<" "<<u<<"\n",void(); } for(int u=1;u<=n;++u) { if(fa[u]&&G[fa[u]].size()==1) H[n-siz[u]].push_back(fa[fa[u]]); for(int v:G[u]) if(G[v].size()==1) H[siz[v]].push_back(G[v][0]); if(A==B&&H[A].size()>1) return cout<<H[A][0]<<" "<<H[A][1]<<"\n",void(); if(A!=B&&H[A].size()&&H[B].size()) return cout<<H[A][0]<<" "<<H[B][0]<<"\n",void(); H[n-siz[u]].clear(); for(int v:G[u]) H[siz[v]].clear(); } dfs2(1); for(int u=n+1;u<=vc;++u) if(G[u].size()>1) { for(int i=0;i<c[u]-1;++i) s[i+1]=s[i+c[u]+1]=siz[G[u][i]],d[i+1]=d[i+c[u]+1]=f[G[u][i]],b[i+1]=b[i+c[u]+1]=G[u][i]; s[c[u]]=s[2*c[u]]=n-siz[u],d[c[u]]=d[2*c[u]]=g[u],b[0]=b[c[u]]=b[2*c[u]]=fa[u]; for(int i=1;i<=2*c[u];++i) s[i]+=s[i-1],pa[i]=pb[i]=xa[i]=xb[i]=0; for(int i=1,j=1,k=1;i<=c[u];++i) { while(s[j]-s[i-1]<A) ++j; while(s[k]-s[i-1]<B) ++k; if(s[j]-s[i-1]==A) pa[i]=j; if(s[k]-s[i-1]==B) pb[i]=k; } for(int i=2*c[u],j=i,k=i;i>c[u];--i) { while(s[i]-s[j-1]<A) --j; while(s[i]-s[k-1]<B) --k; if(s[i]-s[j-1]==A) pa[i]=j; if(s[i]-s[k-1]==B) pb[i]=k; } for(int i=2*c[u],hd=1,tl=0;i;--i) { while(hd<=tl&&d[q[tl]]<=d[i]) --tl; q[++tl]=i; if(i<=c[u]&&pa[i]) { while(hd<=tl&&q[hd]>pa[i]) ++hd; xa[i]=q[hd]; } } for(int i=2*c[u],hd=1,tl=0;i;--i) { while(hd<=tl&&d[q[tl]]<=d[i]) --tl; q[++tl]=i; if(i<=c[u]&&pb[i]) { while(hd<=tl&&q[hd]>pb[i]) ++hd; xb[i]=q[hd]; } } for(int i=1;i<=c[u];++i) if(pa[i]) { auto chk=[&](int lx,int rx,int ly,int ry) { if(ly>ry) return 0; if(ly>c[u]) ly-=c[u],ry-=c[u]; if(s[ry]-s[ly-1]!=B) return 0; int dx=rx-lx+1,dy=ry-ly+1; if(dx%2!=dy%2) return 0; int k=(dx-dy)/2; if(k>0) { if(d[xb[ly]]<k) return 0; for(int x=1;x<=c[u];++x) vis[b[x]]=1; cout<<b[lx+ry-xb[ly]+k]<<" "<<in(b[xb[ly]],k)<<"\n"; return 1; } else { if(d[xa[lx]]<-k) return 0; for(int x=1;x<=c[u];++x) vis[b[x]]=1; cout<<in(b[xa[lx]],-k)<<" "<<b[ly+rx-xa[lx]-k]<<"\n"; return 1; } }; for(int l:{pa[i]+1,pa[i]+2}) for(int r:{i+c[u]-2,i+c[u]-1}) if(chk(i,pa[i],l,r)) return ; } auto chk=[&](int x,int up,int l,int r,int o) { if(!l||!r) return 0; if(r-l+1>=c[u]||r-l+1<(c[u]+1)/2) return 0; int t=r-l+1-(c[u]+1)/2; if(t>up) return 0; for(int i=1;i<=c[u];++i) vis[b[i]]=1; vis[x]=1; int y=in(x,t),z=(o&2?b[r-t]:b[l+t]); if(o&1) swap(y,z); cout<<y<<" "<<z<<"\n"; return 1; }; for(int i=1;i<=c[u];++i) for(int x:G[b[i]]) if(G[x].size()==1) { int j=(i<c[u]?i+1:1),k=(i>1?i+c[u]-1:2*c[u]); if(siz[x]==A&&chk(G[x][0],f[x]-1,j,pb[j],0)) return ; if(siz[x]==B&&chk(G[x][0],f[x]-1,j,pa[j],1)) return ; if(siz[x]==A&&chk(G[x][0],f[x]-1,pb[k],k,2)) return ; if(siz[x]==B&&chk(G[x][0],f[x]-1,pa[k],k,3)) return ; } if(fa[fa[u]]&&G[fa[fa[u]]].size()==1) { int x=fa[fa[u]]; if(n-siz[x]==A&&chk(fa[x],g[x],1,pb[1],0)) return ; if(n-siz[x]==B&&chk(fa[x],g[x],1,pa[1],1)) return ; if(n-siz[x]==A&&chk(fa[x],g[x],pb[2*c[u]-1],2*c[u]-1,2)) return ; if(n-siz[x]==B&&chk(fa[x],g[x],pa[2*c[u]-1],2*c[u]-1,3)) return ; } } } signed main() { ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int _; cin>>_; while(_--) { solve(),dcnt=tp=0; for(int i=0;i<=2*n;++i) { G[i].clear(),E[i].clear(),H[i].clear(); dfn[i]=low[i]=st[i]=ins[i]=0; siz[i]=fa[i]=c[i]=f[i]=g[i]=q[i]=w[i]=0; d[i]=b[i]=s[i]=pa[i]=pb[i]=xa[i]=xb[i]=vis[i]=0; } } return 0; }
- 1
信息
- ID
- 9612
- 时间
- 2000ms
- 内存
- 512MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者