D17 割边 Tarjan 算法
D17 割边 Tarjan 算法_哔哩哔哩_bilibili
1. 割点判定:low[y]>=dfn[x]。允许走反边更新 low 值
割边判定:low[y]>dfn[x]。不允许走反边更新 low 值
2. 若 y 已访问且不是反边,更新 low 值
3. 判反边:链式前向星建图,正反边成对出现
4. bri{a,b} 存割边
#include<bits/stdc++.h> using namespace std; const int N=210,M=10010; int n,m,a,b; int h[N],to[M],ne[M],idx=1; //从2,3开始配对 void add(int a,int b){ to[++idx]=b;ne[idx]=h[a];h[a]=idx; } int dfn[N],low[N],tim,cnt; struct bridge{ int x,y; bool operator<(const bridge &t)const{ if(x==t.x) return y<t.y; return x<t.x; } }bri[M]; //割边 void tarjan(int x,int ine){ dfn[x]=low[x]=++tim; for(int i=h[x];i;i=ne[i]){ int y=to[i]; if(!dfn[y]){ //若y未访问 tarjan(y,i); low[x]=min(low[x],low[y]); if(low[y]>dfn[x]) bri[cnt++]={x,y}; } else if(i!=(ine^1)) //若y已访问且不是反边 low[x]=min(low[x],dfn[y]); } } int main(){ cin>>n>>m; while(m--){ cin>>a>>b; add(a,b),add(b,a); } for(int i=1;i<=n;i++) if(!dfn[i])tarjan(i,0); sort(bri,bri+cnt); for(int i=0;i<cnt;i++) cout<<bri[i].x<<" "<<bri[i].y<<"\n"; }
#include<bits/stdc++.h> using namespace std; const int N=210,M=10010; int n,m,a,b,cnt; struct edge{int u,v;}; vector<edge>e; vector<int>h[N]; int dfn[N],low[N],tim; struct bridge{ int x,y; bool operator<(const bridge &t)const{ if(x==t.x)return y<t.y; return x<t.x; } }bri[M]; void add(int a,int b){ e.push_back({a,b}); h[a].push_back(e.size()-1); } void tarjan(int x,int in_edge){ dfn[x]=low[x]=++tim; for(int i=0;i<h[x].size();i++){ int j=h[x][i], y=e[j].v; if(!dfn[y]){ //若y尚未访问 tarjan(y,j); low[x]=min(low[x],low[y]); if(low[y]>dfn[x]){ bri[cnt++]={x,y}; } } else if(j!=(in_edge^1)) //不是反边 low[x]=min(low[x],dfn[y]); } } int main(){ cin>>n>>m; while(m --){ cin>>a>>b; add(a,b),add(b,a); } for(int i=1; i<=n; i++) if(!dfn[i])tarjan(i,0); sort(bri,bri+cnt); for(int i=0;i<cnt;i++) printf("%d %d\n",bri[i].x,bri[i].y); }
浙公网安备 33010602011771号