P12403 题解
DaiRuiChen007 · · 题解
Problem Link
首先树上
对于基环树上的问题,类似地如果
否则我们只要考虑存在一个不完全同色的环的情况。
枚举该环,必定有一个点在环上,设为
如果有,则粉点和黑点都是区间,且两个区间中间夹了
枚举粉色区间后只有
那么换根 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;
}