題目鏈結:
題目大意:乙個連通圖中,至少新增多少條邊,使得刪除任意一條邊之後,圖還是連通的。
解題思路:
首先來看下邊雙連通分量的定義:
如果任意兩點至少存在兩條「邊不重複」的路徑,那麼說這個圖是邊雙連通的。
那麼本題中,刪除任意一條邊,就可以看作是毀掉一條路徑,那麼只要至少還存在一條路徑即可。
也就是說,轉化成,求加最少的邊,使這個圖邊雙連通。
判斷邊雙連通有兩個方法:
①【侷限性】編號借助low陣列,如果low[u]!=low[v],就代表這兩個點在不同雙連通分量中。
這種方法有些小bug,主要bug在鄰接表這樣的不支援重邊的資料結構上,如果有重邊存在,
那麼即使low[u]!=low[v],u和v也有可能存在於同乙個連通分量中。
所以推薦使用鏈式前向星。
②tarjin時借助並查集,由於橋(刪除之後圖就不連通的邊)不屬於任何雙連通分量,所以在tarjin時,把不是橋的邊的u,v並在一起,
表示u,v在同乙個雙連通分量裡,進行縮點。
下面來看一條結論:
若要使得任意一棵樹,在增加若干條邊後,變成乙個雙連通圖,那麼
至少增加的邊數 =( 這棵樹總度數為1的結點數 + 1 )/ 2。
這樣,只需要統計一下縮點之後每個點的度數即可。
①方法low[u]中存的就是縮點編點,②方法並查集find之後也是縮點編號,degree[編號]記錄度數。
注意,由於本題是無向圖,對於每條邊,只需degree[low[u]]++即可,不用管v。否則每個點的degree要除以2.
最後ans=(leaf+1)/2.
#include "cstdio
"#include
"cstring
"#include
"iostream
"using
namespace
std;
#define maxn 2005
struct
edge
e[maxn*2
];int
pre[maxn],dfs_clock,low[maxn],degree[maxn],head[maxn],tol;
void addedge(int u,int
v)int dfs(int u,int
fa)
else
if(pre[v]min(lowu,pre[v]);
}return low[u]=lowu;
}int
main()
for(int i=1;i<=n;i++) if(!pre[i]) dfs(i,-1
);
for(int u=1;u<=n;u++)
}int leaf=0
;
for(int i=1;i<=n;i++)
if(degree[i]==1) leaf++;
printf(
"%d\n
",(leaf+1)/2
); }
}
2912106
neopenx
poj3352
accepted
4136
16c++
1589
2014-10-31 15:22:43
poj 3352 邊雙連通分量
思路 可以求出所有的橋,把橋刪掉。然後把所有的連通分支求出來,顯然這些連通分支就是原圖中的雙連通分支。把它們縮成點,然後添上剛才刪去的橋,就構成了一棵樹。在樹上添邊使得樹變成乙個雙連通分支即可,這裡我們可以直接統計縮點後的葉子節點個數即可,從而要加的邊數即為 葉子節點個數 1 2.1 include...
poj3352 邊 雙聯通分量
題意 給乙個無向圖,問最少加幾條邊變成邊 雙聯通 題解 求一次雙聯通,縮點,這樣就變成了一棵樹,結果就是 樹上的葉子節點 1 2,葉子節點可以通過入度判斷 include include include include include include include include include ...
poj3694 邊 雙連通分量 lca
題意 先給了一張無向圖,然後依次加邊,每次求橋的數量 題解 先用一次tarjan,我們可以標記橋的位置和記錄橋的數量同時記錄fa陣列,然後更新邊的時候我們可以用lca,因為在tarjan縮點之後得到了一顆樹,當連線a,b節點時,可以直觀的看出從a,b的最近公共祖先到a,b之間所有的橋都會消失,我們可...