Poj 3177 雙聯通分量

2022-05-21 02:56:05 字數 1429 閱讀 3707

[題目大意]

[分析題解]

[個人**]

[相關鏈結]  

[啟發總結]

特別是第四個!以前我了解了low的定義,但是卻沒有發現這個區別:我們平時使用的low,都是其子孫通過

一條返祖邊直接到達的點來決定的。如果我們把這個限制取消掉,按照其提供的做法,可以很簡單的對雙聯通分量進行染色。

poj3177

求新增多少條邊可變連通圖。

接著poj3352的看。對於這種題,我們正常的做法是求橋,刪橋,求連通分支,縮點,構建新圖,求葉子數。

我們有一種簡便方法。需要對tarjan演算法做一些變化。我們之前規定low[u]是其子孫通過一條返祖邊直接到達的點,把這個改成是其子孫可以連續通過多條返祖邊所能到達的點。那麼low[u]=min(low[v],dfn[u]);

這樣做的缺陷是,不能求割點了,多次返祖會導致求割點的錯誤,在多環兩兩以單個點相連排成一條線,且每兩個連線點間只有一條邊的情況中,那些連線點本應是割點,但是在dfs過程中,這些連線點之間的邊又恰好不是樹枝邊的話,low[u]可能會通過多次返祖,從乙個割點不斷的經過這些割點到達最上邊的割點才記錄下low[u]。

這樣中間的割點就都不符合dfn(u)<=low[v]了。

但是這樣做有乙個好處,就是所有的對於邊的雙連通分支都以low標記出來了,即屬於同一雙連通分支的所有點的low都等於同乙個值。因為在不遇到橋的情況下,low可以返祖到該連同分支在遍歷樹中的最高點(dfn最小的點)。

這樣就相當於整理出了所有的對於邊的雙連通分支。我們直接遍歷所有的邊,觀察邊的兩端點是否屬於同一分支,若不屬於則修改兩點的度數。然後看有多少個度數為1的點即可。

這題有重邊,注意判斷。

#include 

#include 

#include 

#include 

using

namespace std;

#define maxn 5005

#define maxm 10005

struct edge

edge[maxm];

int n, m;

int head[maxn];

bool hash[maxn][maxn];

int ecount, tcount;

int dfn[maxn], vis[maxn], low[maxn], degree[maxn];

void addedge(int a, int b)

void input()

}void dfs(int fa, int u)

}int tarjan()

for (int i = 0; i 

if (degree[i] == 1)

ret++;

return (ret + 1) / 2;

}int main()

poj3177 雙連通分量

無向圖,存成有向圖,一條邊存成兩條 強連通的時候就會導致重邊形成環,用fa記錄來自的邊,注意並且用flag判斷是否只有一條那樣的反向邊 求需要添多少條邊成雙連通,記度為1的強連通分量數為ans,結果為 ans 1 2 include include include includeusing name...

poj 3177 邊連通分量

思路 dfs求出所有點的low值,然後對每個連通分量進行縮點,可以通過low來進行縮點。雖然在同一連通分量裡可能存在不同的low值,但這並不影響縮點。將每個連通分量縮為乙個點後,只要求出這個縮點後的樹上的葉子節點個數就行了。結果為 leaf 1 2。include include include i...

邊雙聯通分量

首先什麼是邊雙聯通分量?邊雙連通分量是指,在 無向圖 中刪除任意一條邊依舊聯通的聯通塊 之前講過強連通分量,這裡邊雙聯通分量的做法也需要利用tarjan演算法獲得邊雙聯通分量。對於邊雙聯通分量中還有乙個概念,就是橋。橋指的是 刪除該邊圖不再連通。對應的另乙個概念是 割點 割點的的是 如果除去此節點和...