用的大致是目前题解区第三篇题解的思路
(我拓扑排序排的是边,感觉应该是可行的)
(以及也听从了讨论区其他奆佬的建议,在找的时候把树边的重边跳过了,但是依然没有效果)
贴个代码(马蜂很丑,抱歉orz)
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
int n,m;
const int N=1e5+10,M=N;
struct E{
bool flag;
int x,y;
int id;
};
vector<E> e;
bool cmpA(E a,E b){
return a.flag<b.flag;
}
map<pii,int> id;
int to[M],nt[M],idx,h[N];
inline void add(int x,int y){
to[idx]=y;
nt[idx]=h[x];
h[x]=idx++;
}
const int D=17;
int depth[N];
int zu[N][D+3];
void dfs(int u,int fa){
depth[u]=depth[fa]+1;
zu[u][0]=fa;
for(int k=1;k<=D;k++){
zu[u][k]=zu[zu[u][k-1]][k-1];
}
for(int i=h[u];i!=-1;i=nt[i]){
int j=to[i];
if(j!=fa) dfs(j,u);
}
}
const int G=2e5+10;
int rk[G];
struct topo_graph{
int to[G],nt[G],idx,h[G];
int ru[G];
inline void init(){
idx=0;
memset(h,-1,sizeof(h));
}
inline void add(int x,int y){
to[idx]=y;
nt[idx]=h[x];
h[x]=idx++;
ru[y]++;
}
int q[G],tt,hh;
void toposort(){
tt=-1,hh=0;
for(int i=0;i<m;i++){
if(ru[i]==0) q[++tt]=i;
}
while(hh<=tt){
int u=q[hh++];
for(int i=h[u];i!=-1;i=nt[i]){
int j=to[i];
ru[j]--;
if(ru[j]==0) q[++tt]=j;
}
}
for(int i=0;i<=tt;i++) rk[q[i]]=i;
}
} g;
void LCA(int x,int y){ //x先于y的情况
for(int k=D;k>=0;k--){
if(depth[zu[x][k]]>=depth[y]){
x=zu[x][k];
}
}
if(x==y) return ;
for(int k=D;k>=0;k--){
if(zu[x][k]!=zu[y][k]){
x=zu[x][k];
y=zu[y][k];
}
}
int lca=zu[x][0];
pii X=(pii){min(lca,x),max(lca,x)};
pii Y=(pii){min(lca,y),max(lca,y)};
g.add(id[X],id[Y]);
}
bool cmp(E a,E b){
return rk[a.id]<rk[b.id];
}
int main(){
scanf("%d%d",&n,&m);
int x,y;
for(int i=0;i<m;i++){
scanf("%d%d",&x,&y);
pii pt=(pii){min(x,y),max(x,y)};
id[pt]=i;
e.push_back((E){false,pt.first,pt.second,i});
}
memset(h,-1,sizeof(h));
for(int i=1;i<=n;i++){
scanf("%d",&x);
if(x!=0){
pii pt=(pii){min(x,i),max(x,i)};
e[id[pt]].flag=true;
add(x,i);
}
}
dfs(1,0);
g.init();
for(int i=0;i<m;i++){
if(e[i].flag) continue;
x=e[i].x,y=e[i].y;
if(depth[x]==depth[y]) continue;
else{
if(depth[x]<depth[y]) swap(x,y);
x=zu[x][0];
LCA(x,y);
}
}
g.toposort();
sort(e.begin(),e.end(),cmp);
for(int i=0;i<m;i++){
printf("%d %d\n",e[i].x,e[i].y);
}
return 0;
}
个人感觉卡点可能是我只建了单向边,用pair存边时无脑小的在前,大的在后