無向圖的連通性與相關問題


無向圖的連通性與相關問題

一、相關概念:

給定一張無向圖\(G=(V,E)\):

1、割點:若\(x\in V\),從圖中刪去x以及與x相連的邊后,圖不連通,則x為割點。

2、割邊:若\(e\in E\),從圖中刪去邊e后,圖不連通,則e為割邊(橋)。

3、點(邊)雙聯通分量:一張圖不存在割點(邊),則此圖為點(邊)雙連通分量。

4、歐拉路、歐拉回路、歐拉圖:若有一條從S到T的路徑,滿足恰好經過每一條邊一次,則該路徑為歐 拉路;特別地,當S=T時,此路為歐拉回路;一張所有點度數都為偶數的連通無向圖為歐拉圖。

二、Tarjan與割邊、割點:

Tarjan能夠在線性時間內求無向圖的割點與割邊。

對於Tarjan算法中定義的相關數組與變量不在贅述,直接講一下判定法則。

割邊判定法則:如果對於當前搜索點x,存在一條邊\(e=(x,y)\),滿足\(low[y]>dfn[x]\),則e為割邊。

code:

void Tarjan(int x,int fx) {
	RG int i,y;
	dfn[x]=low[x]=++Time;
	for(i=head[x];i;i=e[i].next)
		if(!dfn[y=e[i].to]) {
			Tarjan(y,x),low[x]=min(low[x],low[y]);
			if(low[y]>dfn[x]) bri[i]=bri[i^1]=1;//成對儲存,邊從2開始
		}
		else if(y!=fx) low[x]=min(low[x],dfn[y]);
}

割邊判定法則:如果對於當前搜索點x,滿足\(low[y]≥dfn[x]\),則x是割點。

​ 不過,需要注意的是,當x為Tarjan算法的起點時,x至少需要有兩個上述節點才是割點。

void tarjan(int x) {
	RG int i,k,y,num=0;
	dfn[x]=low[x]=++Time;
	for(i=head[x];i;i=e[i].next)
		if(!dfn[y=e[i].to]) {
			tarjan(y),low[x]=min(low[x],low[y]);
			if(dfn[x]<=low[y]) 
				if(x!=RT||++num>1) cut[x]=1;
		}
		else low[x]=min(low[x],dfn[y]);
}

三、Tarjan與雙連通分量

記點雙連通分量為\(v-DCC\),邊雙連通分量為\(e-DCC\)

\(e-DCC\) 求法:去掉圖中的所有的割邊,剩下的每一個連通塊都是一個$e-DCC $(直接dfs即可)。

\(e-DCC\) 縮點:直接把每一個連通塊對應一個節點即可,可以得到一棵樹(或森林)。

void dfs(int x) {// 划分連通塊
	RG int i,y;
	vis[x]=1,bel[x]=cnt;// 標記該點為所在e-DCC編號
	for(i=head[x];i;i=e[i].next)
		if(!vis[y=e[i].to]&&!bri[i]) dfs(y);
}

\(v-DCC\) 求法:不是直接去掉所有的割點,剩下的每一個連通塊都是一個\(v-DCC\)

​ 因為一條割邊只能在一個\(e-DCC\)中,但是一個割點去能在多個\(v-DCC\)中。

​ 所以可以用棧維護一下經過的節點,當存在\(low[y]≥dfn[x]\)成立時,無論x是否為根,都彈棧到y為止

​ 所有這些彈出來的點與點x構成一個\(v-DCC\)

\(v-DCC\) 縮點:每一個的\(v-DCC\)看成一個節點,同時每一個割點也單獨看成一個節點。

​ 每一個\(v-DCC\)向它包含的每一個割點連邊,得到一顆樹。事實上這棵樹很棒!(下方的鏈接隨筆e.e.)

​ 割點的記錄在新建的點上,其他點記錄在對應的\(v-DCC\)上。

for(i=1;i<=n;++i)
	if(cut[i]) bel[i]=++cnt,mtx[cnt]=1;
for(i=1,New();i<=cnt;++i)
	for(j=0;j<vec[i].size();++j) // vec 存的是v-DCC的節點(含割點)
		if(cut[x=vec[i][j]]) make(i,bel[x]);
		else bel[x]=i;

利用縮點,我們就可以進一步解決有關無向圖必經邊、必經點的問題!←想了解?←。

四、歐拉路問題

無解判定:當且僅當每個點的度都為偶數才存在歐拉回路。

此處僅貼一下\(dfs\)求歐拉回路的模板(遞歸版):

void dfs(int x) {
	RG int i,y;
	for(i=head[x];i;i=e[i].next) {
		y=e[i].id;
		if(!vis[y]) vis[y]=1,dfs(e[i].to),sta[++top]=y;
        // 將棧中的節點倒序輸出就是一條具體的歐拉回路方案
	}
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM