图论 —— 图的连通性 —— Tarjan 缩点
生活随笔
收集整理的這篇文章主要介紹了
图论 —— 图的连通性 —— Tarjan 缩点
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
縮點(diǎn)常應(yīng)用于給一個(gè)有向圖,求在圖中最少要加多少條邊能使得該圖變成一個(gè)強(qiáng)連通圖
首先求出該圖的各個(gè)強(qiáng)連通分量,然后把每個(gè)強(qiáng)連通分量看出一個(gè)點(diǎn)(即縮點(diǎn)),最后得到了一個(gè)有向無(wú)環(huán)圖(DAG)
對(duì)于一個(gè)DAG,需要添加 max(a,b) 條邊才能使其強(qiáng)連通
其中 a 為 DAG 中出度為 0 的點(diǎn)總數(shù),b 為 DAG 中入度為 0 的點(diǎn)總數(shù)
int n,m; vector<int> G[N]; stack<int> S; int dfn[N],low[N]; bool vis[N];//標(biāo)記數(shù)組 int sccno[N];//記錄結(jié)點(diǎn)i屬于哪個(gè)強(qiáng)連通分量 bool in[N],out[N];//記錄入度、出度是否為0 int block_cnt;//時(shí)間戳 int sig;//記錄強(qiáng)連通分量個(gè)數(shù) void Tarjan(int x){vis[x]=true;dfn[x]=low[x]=++block_cnt;//每找到一個(gè)新點(diǎn),紀(jì)錄當(dāng)前節(jié)點(diǎn)的時(shí)間戳S.push(x);//當(dāng)前結(jié)點(diǎn)入棧for(int i=0;i<G[x].size();i++){//遍歷整個(gè)棧int y=G[x][i];//當(dāng)前結(jié)點(diǎn)的下一結(jié)點(diǎn)if(vis[y]==false){//若未被訪問(wèn)過(guò)Tarjan(y);low[x]=min(low[x],low[y]);}else if(!sccno[y])//若已被訪問(wèn)過(guò),且不屬于任何一個(gè)連通分量low[x]=min(low[x],dfn[y]);}if(dfn[x]==low[x]){//滿足強(qiáng)連通分量要求sig++;//記錄強(qiáng)連通分量個(gè)數(shù)while(true){//記錄元素屬于第幾個(gè)強(qiáng)連通分量int temp=S.top();S.pop();sccno[temp]=sig;if(temp==x)break;}} } void shrink(){//縮點(diǎn)memset(in,false,sizeof(in));memset(out,false,sizeof(out));for(int i=1;i<=sig;i++){//對(duì)于所有的強(qiáng)連通分量,將其入度、出度均視為1in[i]=true;out[i]=true;}for(int x=0;x<n;x++){//枚舉n個(gè)點(diǎn)for(int i=0;i<G[x].size();i++){//對(duì)第x個(gè)點(diǎn)的每個(gè)后繼節(jié)點(diǎn)int y=G[x][i];if(sccno[x]!=sccno[y]){//統(tǒng)計(jì)每個(gè)點(diǎn)出度、入度是否為0out[sccno[x]]=false;in[sccno[y]]=false;}}} } int main() {int t;scanf("%d",&t);while(t--){scanf("%d%d",&n,&m);for(int i=0;i<n;i++)G[i].clear();while(m--){int x,y;scanf("%d%d",&x,&y);x--;y--;G[x].push_back(y);}sig=0;block_cnt=0;memset(vis,false,sizeof(vis));memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));memset(sccno,0,sizeof(sccno));//Tarjan求強(qiáng)連通分量for(int i=0;i<n;i++)if(vis[i]==false)Tarjan(i);shrink();//縮點(diǎn)int a=0,b=0;for(int i=1;i<=sig;i++){//統(tǒng)計(jì)入度、出度為0的點(diǎn)的個(gè)數(shù)if(in[i])a++;if(out[i])b++;}int res=max(a,b);if(sig==1)//強(qiáng)連通分量為1時(shí)res=0;printf("%d\n",res);} }總結(jié)
以上是生活随笔為你收集整理的图论 —— 图的连通性 —— Tarjan 缩点的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 训练日志 2019.2.10
- 下一篇: Fence(CF-324F)