对于u的子节点j,若有low[j] > dfn[u],说明只要不走u-j这条路,从j的搜索树出发无法到达x或比x更早访问的节点
#include<bits/stdc++.h>
using namespace std;
const int N = 100010, M = N * 2;
int idx, h[N], ne[M], e[M], dfn[N], low[N], cnt;
bool bridge[M];
int n, m;
void add(int a, int b){
e[idx] = b; ne[idx] = h[a]; h[a] = idx ++ ;
}
void tarjan(int u, int in_edge){
dfn[u] = low[u] = ++ cnt;
for(int i = h[u]; i != -1; i = ne[i]){
int j = e[i];
if(dfn[j] == 0){
tarjan(j, i);
low[u] = min(low[u], low[j]); // 回去时更新
if(low[j] > dfn[u]){
bridge[i] = bridge[i ^ 1] = true; // i 和 i ^ 1标记一对双向边
}
} else if(i != (in_edge ^ 1)){
low[u] = min(low[u], dfn[j]); // 不是搜索树上的边
}
}
}
int main(){
memset(h, -1, sizeof h);
cin >> n >> m;
idx = 2;
while(m -- ){
int a, b;
cin >> a >> b;
add(a, b);
add(b, a);
}
tarjan(1 ,0);
for(int i = 2; i < idx; i += 2){
if(bridge[i]){
printf("%d %d\n", e[i ^ 1], e[i]);
}
}
return 0;
}
//9 11
//1 2
//1 5
//1 6
//2 3
//2 5
//3 4
//4 5
//6 7
//6 8
//6 9
//8 9