[CTS2024] 众生之门
小清新构造题。
观察大样例可以发现答案不大于 \(3\),感性猜测可以在路径长度不超过 \(3\) 的情况下遍历整棵树,事实也确实如此。
进一步考虑答案一般为 \(0\) 和 \(1\),只有 \(n\) 比较小或者图为菊花时答案是固定的。
所以我们对较小的 \(n\) 跑暴力,菊花图特判,对其余情况随机一个排列,每次交换两项,直到答案小于等于 \(1\) 输出即可。
由于答案值域是 \(O(n)\) 的,所以期望也是 \(O(n)\) 次找到答案,复杂度没问题。
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>
#define PLI pair<ll,int>
#define PIL pair<int,ll>
#define PLL pair<ll,ll>
#define fi first
#define se second
#define YES() cout<<"YES\n",0
#define NO() cout<<"NO\n",0
#define Yes() cout<<"Yes\n",0
#define No() cout<<"No\n",0
using ll=long long;
using uint=unsigned int;
using ull=unsigned long long;
using lb=long double;
const int N=5e4+5;
int T,n,s,t,dep[N],p[N],ANS,ans[N];
int siz[N],wc[N],top[N],fa[N];
vector<int>e[N];
void dfs1(int now,int f){siz[now]=1,wc[now]=0,fa[now]=f;for(auto it:e[now]){if(it!=f){dep[it]=dep[now]+1;dfs1(it,now);siz[now]+=siz[it];if(siz[it]>siz[wc[now]]) wc[now]=it;}}
}
void dfs2(int now,int Top){top[now]=Top;if(wc[now]) dfs2(wc[now],Top);for(auto it:e[now]){if(it!=fa[now]&&it!=wc[now]) dfs2(it,it);}
}
int LCA(int x,int y){while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);x=fa[top[x]];}return dep[x]<dep[y]?x:y;
}
bool flower(){for(int i=1;i<=n;i++) if(e[i].size()==n-1) return 1;return 0;
}
int dis(int x,int y){return dep[x]+dep[y]-2*dep[LCA(x,y)];}
mt19937 rd(std::random_device{}());
int main(){ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);cin>>T;while(T--){cin>>n>>s>>t;for(int i=1;i<=n;i++) e[i].clear();for(int i=1,u,v;i<n;i++){cin>>u>>v;e[u].push_back(v);e[v].push_back(u);}dep[1]=0;dfs1(1,1),dfs2(1,1);if(n<=8){ANS=10;for(int i=1;i<=n;i++) p[i]=i;do{if(p[1]!=s||p[n]!=t) continue;int tmp=0;for(int i=2;i<=n;i++) tmp^=dis(p[i],p[i-1]);if(tmp<ANS){ANS=tmp;for(int i=1;i<=n;i++) ans[i]=p[i];} }while(next_permutation(p+1,p+n+1));for(int i=1;i<=n;i++) cout<<ans[i]<<" ";cout<<"\n";}else{p[1]=s,p[n]=t;
// for(int i=2;i<=n-1;i++) ans[i]=p[i]=i-1+(i-1>=s)+(i-1+(i-1>=s)>=t);for(int i=1;i<=n;i++)if(i!=s&&i!=t) p[i-(i>s)-(i>t)+1]=i;if(flower()){for(int i=1;i<=n;i++) cout<<p[i]<<" ";cout<<"\n";continue;}int tmp=0;for(int i=2;i<=n;i++) tmp^=dis(p[i],p[i-1]);while(tmp>1){int l=rd()%(n-2)+2,r=rd()%(n-2)+2;while(l==r) r=rd()%(n-2)+2;tmp^=dis(p[l],p[l-1])^dis(p[l],p[l+1])^dis(p[r],p[r-1])^dis(p[r],p[r+1]);swap(p[l],p[r]);tmp^=dis(p[l],p[l-1])^dis(p[l],p[l+1])^dis(p[r],p[r-1])^dis(p[r],p[r+1]);}for(int i=1;i<=n;i++) cout<<p[i]<<" ";cout<<"\n";}}
}