目錄
割點:割邊:
tarjan求強連通分量的個數,前面介紹過,在這裡稍微一略過。在有向圖中,尋找乙個點所能到達的最小的時間戳(回溯的被遍歷個數最小的編號)。對於乙個結點u,那麼low[u]肯定是本身++time和所有子節點low[v]的最小的乙個(v可到達的,u都可以到達),更友好的是,點可以多次經過(存在重邊或者兩點形成環等),所以可得核心**:
for(int i = head[u];i != -1;i = edge[i].next)
else if(vis[v]) low[u] = min(low[v],low[u]);
}
vis代表仍在棧中,也就是從棧低元素一路走過來,所以u如果可以到已訪問的v(祖先節點),則必成環,必在乙個強連通分量中,所以用low[v]早更新也一樣。
割點:刪除該點後,乙個圖分成了兩個連通分支。意味著該點所有的子節點最多可以回溯到該割點本身,不可能不經過父節點的情況下回溯更早。
因為不可以經過父節點,所以修改的第一條:
else if(vis[v]) low[u] = min(low[v],low[u]);中的low[u] = min(low[v],low[u]);比如v把該圖分成左右兩部分,v連線起來。u在右側,如果v的low是比v要小的話,這時候u就更新為了low[v],u回溯到了左側,但是經過了v,所以需要改為:
low[u] = min(low[u],dfn[v]);對於根節點,如果可以遍歷一遍全部完成就肯定不是割點,否則必為割點,記錄下即可。
**:
#include#include#include#include#include#include#include#include#includeusing namespace std;
typedef long long ll;
const int maxn = 2e5+50;
struct ededge[maxn];
int head[maxn];
int dfn[maxn],low[maxn];
bool vis[maxn];
int tme = 0,tot = 0;
void add(int u,int v)
void tarjan(int u,int root,int fa)
else if(fa!=v) low[u] = min(low[u],dfn[v]);
//與求強連通分量區別在於low[u]=min(low[u],low[v])在這裡會出錯。
//因為強連通分量v一定是在棧中,也就是肯定是在乙個強連通分量中
//早更新晚更新都無所謂
//並且強連通分量是允許經過父節點!!! 這個不允許。
}}int main()
for(int i = 1;i <= n;i++)
if(!dfn[i]) tarjan(i,i,i);
vectorans;
for(int i = 1;i <= n;i++)
if(vis[i]) ans.push_back(i);
cout《割邊:刪除該邊後,乙個圖變為兩個連通分支。
割點是還能不經過父節點還存在回溯到父節點的情況。割邊的話是根本沒法回到父節點。相比割點,只需改下:if(low[v] > dfn[u])即可。
細節區別:根節點無需特判,不可用結點標記計數,因為乙個結點可能連線多個割邊。
**:#include#include#include#include#include#include#include#include#includeusing namespace std;
typedef long long ll;
const int maxn = 4e6+50;
struct ededge[maxn];
int ans = 0;
int head[maxn];
int dfn[maxn],low[maxn];
bool vis[maxn];
int tme = 0,tot = 0;
void add(int u,int v)
void tarjan(int u,int fa)
else if(fa != v) low[u] = min(low[u],dfn[v]);
}}int main()
for(int i = 1;i <= n;i++)
if(!dfn[i]) tarjan(i,i);
cout
}
割點 割邊 tarjan
洛谷割點模板題 傳送門 割邊 在連通圖中,刪除了連通圖的某條邊後,圖不再連通。這樣的邊被稱為割邊,也叫做橋。割點 在連通圖中,刪除了連通圖的某個點以及與這個點相連的邊後,圖不再連通。這樣的點被稱為割點。dfs搜尋樹 用dfs對圖進行遍歷時,按照遍歷次序的不同,我們可以得到一棵dfs搜尋樹。樹邊 在搜...
割點割頂tarjan
原題 首先tarjan求割點的重點就是dfn和low陣列的理解。dfn i 就是時間戳,即在什麼時刻搜尋到了點i,low i 則是i點能回溯到的dfn最小的祖先,搜尋的時候判斷一下當對於點x存在兒子節點y,使得dfn x low y 則x一定是割點。因為只要x的子節點不能回溯到x的上面,就是沒有返祖...
tarjan割點,割邊 模板
寫的很好的一篇部落格 根節點 如果有2 個或以上 的兒子就 是割 點根節點如果有2個或以上的兒子就是割點 根節點如果有 2個或以 上的兒子 就是割點 因為去掉根節點這兩個兒子就分離了考慮其 他情 況考慮其他情況 考慮其他情況當存 在一條邊 u v當存在一條邊u v 當存在一條邊 u v 且 lo w...