1. 程式人生 > >Tarjan演算法--求無向圖的割點和橋

Tarjan演算法--求無向圖的割點和橋

一.基本概念

1.橋:是存在於無向圖中的這樣的一條邊,如果去掉這一條邊,那麼整張無向圖會分為兩部分,這樣的一條邊稱為橋無向連通圖中,如果刪除某邊後,圖變成不連通,則稱該邊為橋。
2.割點:無向連通圖中,如果刪除某點後,圖變成不連通,則稱該點為割點。

二:tarjan演算法在求橋和割點中的應用

1.割點:1)當前節點為樹根的時候,條件是“要有多餘一棵子樹”(如果只有一顆子樹,去掉這個點也沒有影響,如果有兩顆子樹,去掉這點,兩顆子樹就不連通了。)
          2)當前節點U不是樹根的時候,條件是“low[v]>=dfn[u]”,也就是在u之後遍歷的點,能夠向上翻,最多到u,如果能翻到u的上方,那就有環了,去掉u之後,圖仍然連通。
                                               保證v向上最多翻到u才可以
2.橋:若是一條無向邊(u,v)是橋,
        1)當且僅當無向邊(u,v)是樹枝邊的時候,需要滿足dfn(u)<low(v),也就是v向上翻不到u及其以上的點,那麼u--v之間一定能夠有1條或者多條邊不能刪去,因為他們之間有一部分無環,是橋。
        如果v能上翻到u那麼u--v就是一個環,刪除其中一條路徑後,能然是連通的。
3.注意點:
        1)求橋的時候:因為邊是無方向的,所以父親孩子節點的關係需要自己規定一下,
                            在tarjan的過程中if(v不是u的父節點) low[u]=min(low[u],dfn[v]);
                           因為如果v是u的父親,那麼這條無向邊就被誤認為是環了。
        2)找橋的時候:注意看看有沒有重邊,有重邊的邊一定不是橋,也要避免誤判。
4.也可以先進行tarjan(),求出每一個點的dfn和low,並記錄dfs過程中的每個點的父節點,遍歷所有點的low,dfn來尋找橋和割點

三:求橋和割點的模板:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;
#define N 205
vector<int>G[N];
int n,m,visx,fa[N],low[N],dfn[N];
bool is_cut[N];
void Tarjan(int u,int from) {
    low[u]=dfn[u]=++visx;
    fa[u]=from;
    for
(int i=0; i<G[u].size(); i++) { int k=G[u][i]; if(dfn[k]==-1) { Tarjan(k,u); low[u]=min(low[u],low[k]); } else if(from!=k) low[u]=min(low[u],dfn[k]); } } void count() { int rootson=0; Tarjan(1,-1); for(int i=2; i<=n; i++) { int
v=fa[i]; if(v==1) rootson++; else { if(low[i]>=dfn[v])//判斷割點 is_cut[v]=true; } } if(rootson>1) is_cut[1]=true; for(int i=1; i<=n; i++) if(is_cut[i])printf("%d\n",i); for(int i=1; i<=n; i++) { int v=fa[i]; if(v>0&&low[i]>dfn[v]) printf("%d,%d\n",v,i); } } int main() { scanf("%d%d",&n,&m); memset(fa,0,sizeof(fa)); memset(low,-1,sizeof(low)); memset(dfn,-1,sizeof(dfn)); memset(is_cut,false,sizeof(is_cut)); for(int x,y,i=1; i<=m; i++) { scanf("%d%d",&x,&y); G[x].push_back(y); G[y].push_back(x); } count(); return 0; }

相關推薦

Tarjan演算法--

一.基本概念 1.橋:是存在於無向圖中的這樣的一條邊,如果去掉這一條邊,那麼整張無向圖會分為兩部分,這樣的一條邊稱為橋無向連通圖中,如果刪除某邊後,圖變成不連通,則稱該邊為橋。 2.割點:無向連通圖中

tarjan演算法——

一.基本概念 1.橋:是存在於無向圖中的這樣的一條邊,如果去掉這一條邊,那麼整張無向圖會分為兩部分,這樣的一條邊稱為橋無向連通圖中,如果刪除某邊後,圖變成不連通,則稱該邊為橋。 2.割點:無向連通圖中,如果刪除某點後,圖變成不連通,則稱該點

POJ1144 Network (Tarjan演算法

Network Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 15194 Accepted: 6906 Description A Telephone Lin

2018/2/11 每日一學

return set else 所有 scanf ear .net 存在 sin 割頂和橋:對於無向圖G,如果刪除某個節點u後,連通分量數目增加,則稱u為圖的割頂;如果刪除某條邊後,連通分量數目增加,則稱該邊為圖的橋。 對於連通圖刪除割頂或橋後都會使得圖不再連通。 我們利用

Tarjan演算法連通&&

/** 割點割邊挺好理解的,割點就是一個無向連通圖,把其中一個點 挖掉剩下的圖不連通,割邊就是把一條邊砍掉不連通 比如:有一個通訊網路,要求一顆炸彈,把這個通訊網路搞得不連通,問 炸哪個點或哪條邊。 Tarjan 演算法實現求割邊

頂與

#include<cstdio> #include<cstring> #include<vector> using namespace std; const int maxn=100000+10; int n,m; int dfs_clock;//時鐘,每訪問一個

poj 1523 所有以及刪除後連通分量個數 給出詳細演算法思路

題意 無向圖找出每個割點,然後求出刪除這個割點所得的連通分量個數 節點編號在1-1000,但沒說按順序給出 思路 無向圖求所有割點是一類經典問題,這篇blog就以這題為例簡單介紹一下求解的演算法思路 我們希望在O(n+m)的時間裡求出所有的割

Tarjan演算法求解一個中的問題

基本概念 割點:Articulation Point 在無向連通圖中,刪除一個頂點v及其相連的邊後,原圖從一個連通分量變成了兩個或多個連通分量,則稱頂點v為割點,同時也稱關節點(Articulation Point)。 雙連通的圖:一個沒有關節點的連通圖稱

Tarjan 算法

light cst tar clas 無向圖 oot getchar() als name #include <iostream> #include <cstdio> #include <algorithm> using n

藍橋杯歷屆試題 危險係數(dfs或者並查集關於兩點的個數)

Description 抗日戰爭時期,冀中平原的地道戰曾發揮重要作用。 地道的多個站點間有通道連線,形成了龐大的網路。但也有隱患,當敵人發現了某個站點後,其它站點間可能因此會失去聯絡。 我們來定義一個危險係數DF(x,y): 對於兩個站點x和y (x != y), 如果能找到一個站點z,當

tarjan 模板

#include <bits/stdc++.h> using namespace std; const int MAXN = 20005; const int MAXM = 100005;

hdu4612 中隨意加入一條邊後使的數量最少 / +樹的直徑

child iostream tracking amp min esp _id 矛盾 cstring 題意如上,含有重邊(重邊的話,倆個點就能夠構成了邊雙連通)。 先縮點成樹,在求數的直徑,最遠的連起來,剩下邊(橋)的自然最少。這裏學習了樹的直徑求法:第一次選隨意

Light OJ - 1026 - Critical Links(論-Tarjan算法數) - 帶詳細註釋

tdi lan [] spl 頂點 ace 開始 else lose   原題鏈接   無向連通圖中,如果刪除某邊後,圖變成不連通,則稱該邊為橋。   也可以先用Tajan()進行dfs算出所有點 的low和dfn值,並記錄dfs過程中每個 點的父節點;然後再把所有點

Project-1:設計並實現兩點間所有路徑的演算法

設計並實現求無向圖兩點間所有路徑的演算法 實驗原理 無向圖的深度優先搜尋: 假設一個圖 G,圖中所有頂點未曾被訪問過,則深度優先搜尋就是從圖中某個頂點 v 出發,訪問此頂點,然後再從 v 的未被訪問的鄰接點出發深度優先遍歷圖,直至圖中所有和 v 有路徑相通

的關節點演算法

一、             求無向的圖的關節點的這個演算法是我覺得比較難理解的演算法之一,我覺得難並不是難在算 法本身,而是難在該演算法的遞迴的實現上,特別是在DFSArticul()遞迴退出以後才可以進行 low[]函式的計算,這點,如果是在自己獨立思考來進行程式設

迪傑斯特拉演算法處理中最短路徑的(dijkstra)Java實現(指定兩點,最短距離及路徑)

其實不是原創哈,我寫不出來。       如何求圖中V0到V5的最短路徑呢?         java實現的方式如下:         第一步,根據圖來建立權值矩陣:        int[][] W = {      {  0,   1,   4,  -1,  -

割點(割頂):無向連通圖中,刪除某點後,圖變成不連通,稱該點為割點; 橋:無向連通圖中,如果刪除某條邊後,圖變成不連通,則該邊稱為橋; 定理:在無向連通圖的dfs樹中,非根節點u是割點當且僅當u存在一個子節點v使得v及其所有後代都沒有反向邊連回u的祖先(連回u不算) 求

Fleury演算法 -尤拉的歐拉回路

背景介紹 1) 尤拉圖:存在經過圖中每條邊恰好一次並且僅一次行遍所有點的迴路 通俗來說,該回路有兩個特點: 邊:包括圖中所有邊(不重複地) 點:包括圖中所有點(可重複地) 2) 尤拉圖判斷:

最小

    先解釋下名詞的意思。 無向圖的割:就是去掉一些邊,使得原圖不連通,最小割就是要去掉邊的數量最小。 解決這個問題的常用辦法就是Stoer-Wagner 演算法; 先說下這個演算法的步驟後面給出證明: 1.min=MAXINT,固定一個頂點P 2.從點P用類似prim的

poj3177 Redundant Paths

namespace while paths AI poj AC 新的 所有 mes http://poj.org/problem?id=3177 題意:有n個牧場,互相連通,現在要求使得任意兩個牧場之間至少有兩條道路可走,求至少需要修多少條新的路 -------------