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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Tarjan算法 (强联通分量 割点 割边)

發(fā)布時(shí)間:2025/3/15 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Tarjan算法 (强联通分量 割点 割边) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

變量解釋:
low 指當(dāng)前節(jié)點(diǎn)在同一強(qiáng)連通分量(或環(huán))能回溯到的dfn最小的節(jié)點(diǎn)
dfn 指當(dāng)前節(jié)點(diǎn)是第幾個(gè)被搜到的節(jié)點(diǎn)(時(shí)間戳)
sta 棧
vis 是否在棧中
ans 指強(qiáng)連通分量的數(shù)量
top 棧頂

1.求強(qiáng)連通分量
定義:如果兩個(gè)頂點(diǎn)可以相互通達(dá),則稱兩個(gè)頂點(diǎn)強(qiáng)連通(strongly connected)。如果有向圖G的每?jī)蓚€(gè)頂點(diǎn)都強(qiáng)連通,稱G是一個(gè)強(qiáng)連通圖。有向圖的極大強(qiáng)連通子圖,稱為強(qiáng)連通分量(strongly connected components)。

算法:在有向圖中從一點(diǎn)(u)開始dfs,記錄dfn,搜到一個(gè)已在棧中的點(diǎn)(v)時(shí)用dfn[v] (low[v]也行,但只有求強(qiáng)連通分量時(shí)可以別的只能用dfn[v]) 嘗試更新low[u],并在回溯時(shí)更新沿路的點(diǎn)的low值,走到low值與dfn相同的點(diǎn)時(shí)記錄這個(gè)強(qiáng)連通分量即可。
也就是說:在同一個(gè)強(qiáng)連通分量中所有點(diǎn)low值相同,也就是有一個(gè)代表點(diǎn)(代表點(diǎn)即所有點(diǎn)的low值即強(qiáng)連通分量中dfn值最小的點(diǎn))
時(shí)間復(fù)雜度為O(E+V)

code

void tarjan(int u){dfn[u]=low[u]=++cnt;//初始化一點(diǎn)的dfn和lowsta[++top]=u,vis[u]=true;//入棧for(int i=head[u];i;i=edge[i].next){//鄰接表int v=edge[i].to;if(!dfn[v]){//如果沒走過tarjan(v);low[u]=min(low[u],low[v]);//回溯過程時(shí)low值傳遞}else if(vis[v]) low[u]=min(low[u],dfn[v]); //low[v]也行 用代表點(diǎn)更新}if(dfn[u]==low[u]) {//如果是代表點(diǎn) 記錄并出棧ans++;//記錄強(qiáng)連通分量個(gè)數(shù)while(sta[top]!=u){vis[sta[top]]=false;top--;}vis[sta[top]]=false;top--;}return ; }

2.求無向圖的割點(diǎn)與割邊
割點(diǎn):在無向圖中,如果將一個(gè)點(diǎn)以及所有連接該點(diǎn)的邊都去掉,圖就不再連通,那么這個(gè)點(diǎn)就叫做這個(gè)圖的一個(gè)割點(diǎn)。
割邊:在無向圖中,如果將一條邊去掉,圖就不再連通則稱這條邊為圖的一個(gè)割邊。

求割點(diǎn):如果一個(gè)點(diǎn)(u)所連接的幾個(gè)節(jié)點(diǎn)(v)的low值大或等于此節(jié)點(diǎn)(u)的dfn值時(shí)說明之后的節(jié)點(diǎn)(v)無法連接到比此點(diǎn)(u)更早的點(diǎn)上,則說明這個(gè)節(jié)點(diǎn)(u)是一個(gè)割點(diǎn)。PS:根節(jié)點(diǎn)需特判,當(dāng)根節(jié)點(diǎn)在dfs樹有兩個(gè)或更多個(gè)子樹時(shí)則說明根節(jié)點(diǎn)是割點(diǎn)

求割邊:與割點(diǎn)類似,如果一個(gè)點(diǎn)(u)的dfn值大于(不能等于,否則不一定)和它連接的一個(gè)節(jié)點(diǎn)(v)的low值,則說明這條邊(uv)為圖的一個(gè)割邊

變量解釋:
sum 指總共有幾個(gè)割點(diǎn)(邊)

割點(diǎn)code

void cutpoint(int u){int fl=0;//為特判準(zhǔn)備dfn[u]=low[u]=++cnt;//初始化for(int i=head[u];i;i=edge[i].next){//用鄰接表,下同int v=edge[i].to;if(!dfn[v]){cutpoint(v);low[u]=min(low[u],low[v]);if(u!=root&&low[v]>=dfn[u]&&!cpoint[u]) sum++,cpoint[u]=1;//不是根節(jié)點(diǎn)&&v的low值>=u的dfn值&&此點(diǎn)沒有算過if(u==root) fl++;//此時(shí)特判++}low[u]=min(low[u],dfn[v]); }if(fl>=2&&!cpoint[u]) sum++,cpoint[u]=1;//根節(jié)點(diǎn)若有兩棵子樹則是割點(diǎn) }

割邊code

void cutedge(int u,int f){dfn[u]=low[u]=++cnt;for(int i=head[u];i;i=edge[i].next){int v=edge[i].to;if(!dfn[v]){cutedge(v,u);low[u]=min(low[u],low[v]);if(dfn[u]<low[v]) cedge[++sum]=i;//記錄邊的序號(hào)}else if(v!=f) low[u]=min(low[u],dfn[v]); //只有當(dāng)v不是u的上一個(gè)節(jié)點(diǎn)時(shí)可行} }

完整模板code:
ps:這里就不打注釋了,核心就在上面的部分里

#include<cstdio> #include<iostream> #include<cstring> using namespace std;const int MAX=1000010; int n,m,cnt,sum,root; int head[MAX],low[MAX],dfn[MAX],cpoint[MAX],cedge[MAX];struct edg{int to,next,from; }edge[MAX];void add(int x,int y){edge[++cnt].next=head[x];edge[cnt].from=x,edge[cnt].to=y;head[x]=cnt; }void cutpoint(int u){int fl=0;dfn[u]=low[u]=++cnt;for(int i=head[u];i;i=edge[i].next){int v=edge[i].to;if(!dfn[v]){cutpoint(v);low[u]=min(low[u],low[v]);if(u!=root&&low[v]>=dfn[u]&&!cpoint[u]) sum++,cpoint[u]=1;if(u==root) fl++;}low[u]=min(low[u],dfn[v]); }if(fl>=2&&!cpoint[u]) sum++,cpoint[u]=1; }void cutedge(int u,int f){dfn[u]=low[u]=++cnt;for(int i=head[u];i;i=edge[i].next){int v=edge[i].to;if(!dfn[v]){cutedge(v,u);low[u]=min(low[u],low[v]);if(dfn[u]<low[v]) cedge[++sum]=i;}else if(v!=f) low[u]=min(low[u],dfn[v]);} }void mset(){memset(dfn,0,sizeof dfn);memset(low,0,sizeof low);cnt=sum=0; }void find_cutpoint(){for(int i=1;i<=n;i++) if(!dfn[i]) {root=i;cutpoint(i);}printf("%d\n",sum);for(int i=1;i<=n;i++) if(cpoint[i]) printf("%d ",i); }void find_cutedge(){for(int i=1;i<=n;i++) if(!dfn[i]) cutedge(i,0);printf("%d\n",sum);for(int i=1;i<=sum;i++) printf("%d %d\n",edge[cedge[i]].from,edge[cedge[i]].to); }int main(){ // freopen("testdata.txt","r",stdin);scanf("%d %d",&n,&m);for(int i=1;i<=m;i++){int a,b;scanf("%d %d",&a,&b);add(a,b);add(b,a);}find_cutedge();mset();find_cutpoint();return 0; }

轉(zhuǎn)載于:https://www.cnblogs.com/Menteur-Hxy/p/9248051.html

總結(jié)

以上是生活随笔為你收集整理的Tarjan算法 (强联通分量 割点 割边)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 精品福利三区3d卡通动漫 | 娇妻玩4p被三个男人伺候电影 | 丝袜美女啪啪 | 97caoporn| 最近中文字幕在线中文视频 | 少妇毛片一区二区三区 | 女人黄色片 | 中国一级大黄大黄大色毛片 | 亚洲精品大全 | 久久婷婷五月综合色吧 | 久久亚洲精精品中文字幕早川悠里 | 久久久999 | 欧美黄色免费看 | 国产乱国产乱老熟300部视频 | 亚洲色图导航 | 中文字幕+乱码+中文字幕一区 | 日韩aa视频 | 爱豆国产剧免费观看大全剧集 | 久久成人网18网站 | 久久久99精品国产一区二区三区 | 高跟鞋和丝袜猛烈xxxxxx | 操日本老太太 | 一本色道久久综合亚洲精品图片 | 福利视频一区 | 一区二区中文字幕在线观看 | 成人福利在线播放 | 黑料福利 | 免费黄色大片 | 18禁裸男晨勃露j毛免费观看 | 黄色在线网站 | 日本三级免费网站 | 嫩草一区二区 | 国产精品三区在线观看 | 久久综合伊人 | 美攻壮受大胸奶汁(高h) | 美女扒开尿口让男人爽 | 一炮成瘾1v1高h | 蜜臀精品一区二区三区 | 久久久午夜 | 91午夜在线观看 | 欧美一级片一区 | 欧美丰满熟妇xxxxx | 91久久国产精品 | 天天综合网站 | 先锋av资源网站 | 日本波多野结衣在线 | 自拍偷拍视频网站 | 精品在线小视频 | 人操人爽 | wwwav网站| 中文字幕一区二区三区不卡 | 影音先锋在线中文字幕 | 人人爱爱人人 | 欧美精彩视频 | 亚洲精品粉嫩小泬 | 国产一区视频免费观看 | 欧美精品一二 | 国产无码日韩精品 | 一区二区三区在线观看视频 | 狠狠操狠狠 | 欧美10p| 噼里啪啦动漫高清在线观看 | 日本肉体xxxx裸体137大胆图 | 青青免费在线视频 | 国产富婆一级全黄大片 | 可以免费观看的毛片 | 中文字幕亚洲图片 | 黑人巨大精品欧美一区二区免费 | 放荡闺蜜高h苏桃情事h | 日韩六区| 乱人伦av | 日日干夜夜骑 | 中文不卡av | 国产福利片在线观看 | 精品国产午夜福利 | 国产成人精品一区二区三区福利 | 国产高清av | 91丨porny丨九色 | 日批免费观看视频 | 色播五月综合 | 黄色性情网站 | 成年人免费在线观看 | 爱豆国产剧免费观看大全剧集 | 91麻豆精品国产午夜天堂 | 奶水喷溅虐奶乳奴h文 | 成人手机在线播放 | 亚欧洲精品视频 | 在线观看日韩精品 | 青草视频在线观看免费 | av网站观看| 亚洲AV无码阿娇国产精品 | 一亲二脱三插 | 亚洲特黄特色 | 一区二区在线免费看 | 在线免费观看网站入口在哪 | 蜜桃视频在线观看网站 | 色爱区综合 | 日本黄色小说 | 美女久久久久 |