写了一个 分层图 + LCA + 拓扑 的做法,想问问有么有更优的。
顺便贴一下我的代码。
const int N=2e5+5,L=18;
int x[N],y[N],fr[N<<1],to[N<<1],nxt[N<<1],cnt=1,head[N],fa[N],dep[N],f[N][L];
bool vis[N<<1];
vector <int> col[N];
vector <int> son[N];
vector <int> poi[N];
map <pair<int,int>,int> mm;
int deg[N];
void add(int u,int v){
to[++cnt]=v;
fr[cnt]=u;
nxt[cnt]=head[u];
head[u]=cnt;
}
void init(int u){
dep[u]=dep[fa[u]]+1;
f[u][0]=fa[u];
for(int i=1;i<L;i++) f[u][i]=f[f[u][i-1]][i-1];
for(int i=0;i<son[u].size();i++){
int v=son[u][i];
init(v);
}
}
void lca(int &x,int &y){
if(fa[x]==fa[y]) return;
for(int i=L-1;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
}
void dfs(int u){
for(int i=head[u];i;i=nxt[i]){
int v=to[i];
if(dep[v]==dep[u]-1&&v!=fa[u]){
int x=fa[u],y=v;
lca(x,y);
poi[x].push_back(y);
deg[y]++;
}
}
for(int i=0;i<son[u].size();i++) dfs(son[u][i]);
}
void bfs(int d){
if(col[d].size()==0) return;
queue <int> q;
for(int i=0;i<col[d].size();i++){
int u=col[d][i];
if(deg[u]==0) q.push(u);
}
while(!q.empty()){
int u=q.front();
q.pop();
cout<<u<<' '<<fa[u]<<endl;
mm[{max(u,fa[u]),min(u,fa[u])}]--;
for(int i=0;i<poi[u].size();i++){
int v=poi[u][i];
deg[v]--;
if(deg[v]==0) q.push(v);
}
}
bfs(d+1);
}
void solve(){
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>x[i]>>y[i];
add(x[i],y[i]),add(y[i],x[i]);
mm[{max(x[i],y[i]),min(x[i],y[i])}]++;
}
for(int i=1;i<=n;i++) cin>>fa[i],son[fa[i]].push_back(i);
init(1);
for(int i=1;i<=n;i++) col[dep[i]].push_back(i);
dfs(1);
bfs(2);
for(int i=2;i<=cnt;i+=2) if(mm[{max(to[i],fr[i]),min(to[i],fr[i])}]) cout<<to[i]<<' '<<fr[i]<<endl,mm[{max(to[i],fr[i]),min(to[i],fr[i])}]--;
}