日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

连通图/割点、割边

發(fā)布時(shí)間:2023/12/13 综合教程 27 生活家
生活随笔 收集整理的這篇文章主要介紹了 连通图/割点、割边 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

先了解一下每個(gè)名詞的含義

無向圖:沒有方向的圖
無向連通圖:圖中任意兩節(jié)點(diǎn)可互相到達(dá)的無向圖
無向非連通圖:不是無向連通圖
無相連通分量:無向非連通圖中的最大連通子圖
割點(diǎn):刪掉這個(gè)點(diǎn)就不連通
割邊:刪掉這個(gè)邊就不連通
強(qiáng)聯(lián)通有向圖:任意兩點(diǎn)可以到達(dá)的有向圖
弱連通有向圖:如果忽略邊的方向是一個(gè)無向連通圖
強(qiáng)聯(lián)通分量(SCC):非強(qiáng)連通圖的極大連通子圖

對(duì)于求無向圖中的割點(diǎn)和割邊

為什么有割點(diǎn)和非割點(diǎn)之分,那就是由于無向圖連通有環(huán),環(huán)中的點(diǎn)自然不是割點(diǎn),如果無向連通圖要是樹的話,那么所有點(diǎn)就都是割點(diǎn)了

對(duì)于Tarjan算法,則是選擇一個(gè)為根節(jié)點(diǎn)進(jìn)行dfs搜索,用dfn數(shù)組存儲(chǔ)每個(gè)節(jié)點(diǎn)出現(xiàn)時(shí)間(時(shí)間從1開始,0代表沒搜過)

如果該圖中有環(huán)那么該環(huán)中一定有first(最早出現(xiàn)的節(jié)點(diǎn))和last(最晚出現(xiàn)的節(jié)點(diǎn)),而且last與fisrt有邊能直接相連,當(dāng)last搜尋下一個(gè)節(jié)點(diǎn)時(shí)便會(huì)搜到first

這時(shí)需要一個(gè)low數(shù)組存儲(chǔ)每個(gè)點(diǎn)能搜索到的最早出現(xiàn)的時(shí)間,只有對(duì)于環(huán)中l(wèi)ast搜到fisrt時(shí),low數(shù)組能變小,而且會(huì)讓從fisrt->last這條樹鏈上的所有點(diǎn)i,使得low[i]=min(low[i],dfn[first])(代碼中應(yīng)該是low[u]=min(low[u],low[v]))

搜完所有點(diǎn)以后

若求割點(diǎn)每個(gè)點(diǎn)可以分為根節(jié)點(diǎn)和不是根節(jié)點(diǎn)

對(duì)于根節(jié)點(diǎn),若有兩個(gè)子節(jié)點(diǎn)那么該點(diǎn)即是割點(diǎn)(對(duì)于如何判斷有幾個(gè)子節(jié)點(diǎn),在搜索時(shí)用一個(gè)fa[]數(shù)組存好由誰轉(zhuǎn)移過來的,最后以判斷有幾個(gè)是由根節(jié)點(diǎn)轉(zhuǎn)換的即可)

對(duì)于不是根節(jié)點(diǎn)i,若low[i]>=dfn[fa[i]]則該點(diǎn)父親是割點(diǎn)(因?yàn)樵擖c(diǎn)不通過該點(diǎn)與父親的邊最多只能搜到父親節(jié),那么刪掉父親節(jié)點(diǎn),該點(diǎn)則不能搜到父親以上節(jié)點(diǎn))

若求割邊,只需要搜每個(gè)不是根節(jié)點(diǎn)的點(diǎn)i,若low[i]>dfn[fa[i]]那么該點(diǎn)與父親連的邊為割邊(因?yàn)槿粼擖c(diǎn)所能搜到的最早出現(xiàn)的點(diǎn)也比父親出現(xiàn)的晚,說明該點(diǎn)不能搜到父親上面的點(diǎn))

代碼如下

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std;
int dfn[1005],low[1005],fa[1005];
bool vis[1005];
vector<int>G[1005];
int cnt;
void tarjan(int u)
{
dfn[u]=low[u]=++cnt;
int i,j;
for(i=0; i<G[u].size(); i++)
{
int v=G[u][i];
if(dfn[v]==0)
{
fa[v]=u;
tarjan(v);
low[u]=min(low[u],low[v]);
}
else
low[u]=min(low[u],dfn[v]);
}
}
int gedian(int n)
{
int num=0;
memset(vis,false,sizeof(vis));
int i,j,fu;
for(i=2; i<=n; i++)
{
fu=fa[i];
if(fu==1)
num++;
else
{
if(low[i]>=dfn[fu])
vis[fu]=true;
}
}
if(num>=2)
vis[1]=true;
int sum=0;
for(i=1; i<=n; i++)
{
if(vis[i])
sum++;
}
return sum;
}
int gebian(int n)
{
int i,j,sum=0,fu;
for(i=1;i<=n;i++)
{
fu=fa[i];
if(fu>0&&low[i]>dfn[fu])
sum++;
}
return sum;
}
int main()
{
int n,m;
while(scanf("%d %d",&n,&m)!=EOF)
{
int i,j;
for(i=1; i<=n; i++)
G[i].clear();
int x,y;
for(i=0; i<m; i++)
{
scanf("%d %d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}
memset(dfn,0,sizeof(dfn));
cnt=0;
memset(fa,0,sizeof(fa));
tarjan(1);

}
}
跑一遍taijan以后有向圖變成一棵樹,對(duì)于原圖環(huán)中一定被舍掉,但恰恰由于這條邊改變了low值,因?yàn)闃涠际菑纳现赶蛳拢挥羞@條邊往上指了,使得
該邊下邊點(diǎn)low值可以變成上邊點(diǎn)dfn值
求割點(diǎn)
對(duì)于根如果有兩棵子樹則該點(diǎn)是割點(diǎn)
否則若該點(diǎn)u存在一個(gè)子節(jié)點(diǎn)v使得 low[v]>=dfn[u]則u為割點(diǎn)
求割邊
對(duì)于某條邊的子節(jié)點(diǎn)v父節(jié)點(diǎn)u存在 low[v]>dfn[u]則該邊為割邊

總結(jié)

以上是生活随笔為你收集整理的连通图/割点、割边的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。