洛谷割點模板題——傳送門
割邊:在連通圖中,刪除了連通圖的某條邊後,圖不再連通。這樣的邊被稱為割邊,也叫做橋。
割點:在連通圖中,刪除了連通圖的某個點以及與這個點相連的邊後,圖不再連通。這樣的點被稱為割點。
dfs搜尋樹:用dfs對圖進行遍歷時,按照遍歷次序的不同,我們可以得到一棵dfs搜尋樹。
樹邊:在搜尋樹中的藍色線所示,可理解為在dfs過程中訪問未訪問節點時所經過的邊,也稱為父子邊
回邊:在搜尋樹中的橙色線所示,可理解為在dfs過程中遇到已訪問節點時所經過的邊,也稱為返祖邊、後向邊
觀察dfs搜尋樹,我們可以發現有兩類節點可以成為割點。對根節點u,若其有兩棵或兩棵以上的子樹,則該根結點u為割點;對非葉子節點u(非根節點),若其中的某棵子樹的節點均沒有指向u的祖先節點的回邊,說明刪除u之後,根結點與該棵子樹的節點不再連通;則節點u為割點。對於根結點,顯然很好處理;但是對於非葉子節點,怎麼去判斷有沒有回邊是乙個值得深思的問題。我們用dfn[u]記錄節點u在dfs過程中被遍歷到的次序號,low[u]記錄節點u或u的子樹通過非父子邊追溯到最早的祖先節點(即dfs次序號最小),那麼low[u]的計算過程如下。
對於給的例子,其求出的dfn和low陣列如下。
id 1 2 3 4 5 6
dfn 1 2 3 4 5 6
low 1 1 1 4 4 4
可以發現,對於情況2,當(u,v)為樹邊且low[v]≥dfn[u]時,節點u才為割點。而當(u,v)為樹邊且low[v]>dfn[u]時,表示v節點只能通過該邊(u,v)與u連通,那麼(u,v)即為割邊。tarjan演算法的時間複雜度是o(n+m)的,非常快。
——附帶碼
#include #includeview code#include
#include
#include
using
namespace
std;
const
int maxn = 100001
;int
n, m, cnt, rp;
int next[2 * maxn], to[2 * maxn], head[maxn], low[maxn], dfn[maxn], father[maxn];//
father為父節點
vector cut_point;
vector
< pair >cut_edge;
void add(int x, int
y)void tarjan(int
u)
else
if(v != father[u]) low[u] =min(low[u], dfn[v]);
}//根節點若有兩棵或兩棵以上的子樹則該為割點
//非根節點若所有子樹節點均沒有指向u的祖先節點的回邊則為割點
if((father[u] == 0 && child > 1) || (father[u] &&flag)) cut_point.push_back(u);
}int
main()
for(i = 1; i <= n; i++)//
圖可能不聯通(mdzz的洛谷模板題)
if(!dfn[i])
tarjan(i);
sort(cut_point.begin(), cut_point.end());
s =cut_point.size();
printf(
"%d\n
", s);
for(i = 0; i < s; i++) printf("
%d ", cut_point[i]);//
輸出割點
s =cut_edge.size();
printf(
"\n%d\n
", s);
for(i = 0; i < s; i++) printf("
%d %d\n
", cut_edge[i].first, cut_edge[i].second);//
輸出割邊
return0;
}
經過培訓,發現上面的**如果有重邊就會拉閘。
下面是可以應對重邊的**
1 # include 2 # include 3 # include 4 # includeview code5 # include 6 # include 7 # include 8 # include 9 # include 10 # define maxn 2333
11using
namespace
std;
1213 inline void
file()
2122 inline int
get_num()
2930
intn, m, tim, cnt;
31int
dfn[maxn], low[maxn], f[maxn], to[maxn], next[maxn], head[maxn];
32 vector cut_point;
33 vector < pair >cut_edge;
3435 inline void add(int x, int
y)36
4142 inline void dfs(int u, int
fa)43
60else low[u] =min(low[u], dfn[v]);61}
62if((!f[u] && child > 1) || (f[u] &&flag)) cut_point.push_back(u);63}
6465
intmain()
6678
for(i = 1; i <= n; i++)
79if(!dfn[i])
80 dfs(i, -1
);81
for(i = 0; i < cut_point.size(); i++) printf("
%d\n
", cut_point[i]);
82 puts(""
);83
for(i = 0; i < cut_edge.size(); i++) printf("
%d %d\n
", cut_edge[i].first, cut_edge[i].second);
84 puts(""
);85
return0;
86 }
tarjan割點,割邊 模板
寫的很好的一篇部落格 根節點 如果有2 個或以上 的兒子就 是割 點根節點如果有2個或以上的兒子就是割點 根節點如果有 2個或以 上的兒子 就是割點 因為去掉根節點這兩個兒子就分離了考慮其 他情 況考慮其他情況 考慮其他情況當存 在一條邊 u v當存在一條邊u v 當存在一條邊 u v 且 lo w...
tarjan求割邊割點
內容及 來自 割邊 在連通圖中,刪除了連通圖的某條邊後,圖不再連通。這樣的邊被稱為割邊,也叫做橋。割點 在連通圖中,刪除了連通圖的某個點以及與這個點相連的邊後,圖不再連通。這樣的點被稱為割點。dfs搜尋樹 用dfs對圖進行遍歷時,按照遍歷次序的不同,我們可以得到一棵dfs搜尋樹。樹邊 在搜尋樹中的藍...
tarjan演算法求割點割邊
在上一節我們已經知道tarjan演算法可以求聯通圖,在這裡我們也運用tarjan的思想求割點與割邊,首先我們先來說說割點,那麼什麼事割點呢,先來看一張圖 a 來自網路 在 a 圖中,我們將a點以及與a點相連的邊全部去除,會發現這個聯通圖被分成了倆個聯通圖,乙個是節點f,另外乙個是餘下的所有的節點組成...