圖論算法-Tarjan模板 【縮點;割頂;雙連通分量】
阿新 • • 發佈:2018-02-21
else if false -m 例如 als for 算法思路 連通 tarjan
圖論算法-Tarjan模板 【縮點;割頂;雙連通分量】
為小夥伴們總結的Tarjan三大算法
Tarjan縮點(求強連通分量)
int n; int low[100010],dfn[100010]; bool ins[100010]; int col[100010];//記錄每個點所屬強連通分量(即染色) vector<int> map[100010]; stack<int> st; int tot;//時間戳 int colnum;//記錄強連通分量個數 void tarjan(int u) { low[u]=dfn[u]=++tot; st.push(u); ins[u]=true; for(int j=0;j<map[u].size();j++) { int v=map[u][j]; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(ins[v]) low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]) { //到這裏即發現了一個新的強連通分量 colnum++; int temp; int cont=0; do { temp=st.top(); st.pop(); ins[temp]=false; //將同一強連通分量的點染色,表示一個縮點 col[temp]=colnum; //在這裏也可以對該強連通分量進行一些其他操作 //例如保存該縮點所包含的原節點 } while(temp!=u); } } void init() { memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(col,0,sizeof(col)); memset(ins,false,sizeof(ins)); tot=colnum=0; } void solve() { init(); for(int i=1;i<=n;i++) { if(!dfn[i]) tarjan(i); } }
Tarjan求割點(割頂)
int n; vector<int> map[100010]; int low[100010],dfn[100010]; bool cut[1000010];//記錄割點 int tot; void tarjan(int u,int fa) { low[u]=dfn[u]=++tot; int child=0; for(int j=0;j<map[u].size();j++) { int v=map[u][j]; if(!dfn[v]) { child++; tarjan(v,u); low[u]=min(low[u],low[v]); if(low[v]>=dfn[u]) cut[u]=true; } else if(dfn[v]<dfn[u]&&v!=fa) low[u]=min(low[u],dfn[v]); } if(fa<0&&child==1) cut[u]=false; } void init() { memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(cut,false,sizeof(cut)); tot=0; } void solve() { init(); for(int i=1;i<=n;i++) { if(!dfn[i]) tarjan(i,-1); //**高亮**這裏的第二個參數一定要設為負數 } //cut[i]==true即表示i為割點 }
Tarjan求點-雙連通分量
int n; vector<int> map[100010]; int low[100010],dfn[100010]; bool cut[1000010]; int bcc[1000010]; int tot; int bcc_cont//記錄雙連通分量個數; struct edge{int u,v}; stack<edge> E; void tarjan(int u,int fa) { low[u]=dfn[u]=++tot; int child=0; for(int j=0;j<map[u].size();j++) { int v=map[u][j]; edge e=(edge) {u,v}; if(!dfn[v]) { E.push(e); child++; tarjan(v,u); low[u]=min(low[u],low[v]); if(low[v]>=dfn[u]) { //到這裏即發現了一個新的雙連通分量 cut[u]=true; bcc_cont++: while(1) { edge temp=E.top(); E.pop(); if(bccno[temp.u]!=bcc_cont) bccno[temp.u]=bcc_cont; if(bccno[temp.v]!=bcc_cont) bccno[temp.v]=bcc_cont; if(temp.u==u&&temp.v==v) break; } } } else if(dfn[v]<dfn[u]&&v!=fa) { E.push(e); low[u]=min(low[u],dfn[v]); } } if(fa<0&&child==1) cut[u]=false; } void init() { memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(bccno,0,sizeof(bccno)); tot=bcc_cont=0; } void solve() { init(); for(int i=1;i<=n;i++) { if(!dfn[i]) tarjan(i,-1);//**高亮**這裏的第二個參數一定要設為負數 } }
其實三個算法思路都基本一致
畢竟都是同一個人提出的嘛
圖論算法-Tarjan模板 【縮點;割頂;雙連通分量】