演算法學習之路|強連通分量+縮點
本來寒假是安排的很充實的,放假了一回到家就(ノへ ̄、)
演算法想想還是不能丟,雖然離ACM銅牌的水平還差好遠,但是,不想留下遺憾,演算法慢慢的要重新拾起來的,雖然以前水平也不咋地╯︿╰
原題為2017icpc亞洲區預賽烏魯木齊網路賽F題island
https://nanti.jisuanke.com/t/16955
題目大意:一張有向圖,問至少再新增幾條有向邊,才能使它成為強連通圖。
主要寫一下本題大致用到了哪些方面的知識,理一下思路。
強連通分量:在有向圖中,如果一張圖中的任意兩點都可以相互到達,則稱這個圖為強連通圖。圖中任意兩點之間可以相互到達的子圖即為強連通分量。
tarjan演算法:本質是通過一次dfs搜尋有向圖,用棧儲存到達過的節點,每求出一個完整的強連通分量,就彈出對應的節點,計算強連通分量的個數(即之後縮點後點的個數)。
tarjan演算法的詳解可以看這位博主的部落格:
http://blog.csdn.net/jeryjeryjery/article/details/52829142?locationNum=4
縮點:在每次求得一個強連通分量時,給當前強連通分量中的節點打上同一個標記,看成同一個節點,即縮點。
入度、出度:如有向邊(u,v)不在同一個強連通分量中,則u所在強連通分量出度++,v所在強連通分量入度++。
計算入度為0和出度為0的強連通分量個數n,m
構成強連通圖需要新增的最少邊就是max(n,m),因為出度為0的點無法到達其他節點,入度為0的點無法被到達,則至少使得所有點入度和出度都大於0才能構成強連通圖。
tarjan演算法程式碼:
注意!這不是ac程式碼!(由於用的鄰接矩陣儲存邊,最後記憶體超了)
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define maxn 10005
using namespace std;
int raid[maxn][maxn];
int low[maxn],dfn[maxn],sta[maxn],flag[maxn],suo[maxn],indegree[maxn],outdegree[maxn];
int idex=1,number=0,top=0,n,m;//idex時間戳,number強連通分量個數,top sta棧中位置
void tarjan(int u)
{
int i;
dfn[u]=low[u]=idex++;//dfn訪問的次序,low當前節點能到達的最遠的父親節點的dfn(歸入同一強連通分量)
sta[top++]=u;//入棧
flag[u]=1;//標記為已訪問
for(int v=1;v<=n;v++)
{
if(raid[u][v])
{
if(!dfn[v])//如果v沒有被訪問過
{
tarjan(v);//遞迴呼叫
if(low[u]>low[v])//更新low
low[u]=low[v];
}
else//被訪問過
{
if(dfn[v]<low[u]&&flag[v]==1)//v被訪問過且v在棧中,防止被彈出的節點被誤以為是父親節點
{
low[u]=dfn[v];//指向父親節點
}
}
}
}
//往後回溯,將棧中屬於同一強連通分量的節點全部彈出
if(dfn[u]==low[u])
number++;
do
{
i=sta[top];
flag[i]=0;
suo[i]=number;//縮點,屬於同一強連通分量的節點縮成一個點
top--;
}
while(i!=u);
}
int main()
{
int t,u,v;
scanf("%d",&t);
while(t--)
{
number=0;
idex=1;
top=0;
memset(raid,0,sizeof(raid));
memset(flag,0,sizeof(flag));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(sta,0,sizeof(sta));
memset(suo,0,sizeof(suo));
memset(indegree,0,sizeof(indegree));
memset(outdegree,0,sizeof(outdegree));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
raid[u][v]++;
}
int in=0,out=0,MAX=0;//入度和出度
tarjan(1);//若初始圖不一定連通則需要迴圈呼叫tarjan函式
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(raid[i][j]!=0&&suo[i]!=suo[j])
{
indegree[suo[j]]++;
outdegree[suo[i]]++;
}
}
}
for(int i=1;i<=number;i++)
{
if(indegree[i]==0)
in++;
if(outdegree[i]==0)
out++;
}
MAX=max(in,out);
printf("%d
",MAX);
}
return 0;
}
相關文章
- 【模板】tarjan 強連通分量縮點
- 強連通分量及縮點 演算法解析及例題演算法
- 【演算法學習】tarjan 強連通、點雙、邊雙及其縮點 重磅來襲!!!!演算法
- 強聯通分量及縮點法
- 強連通分量(Tarjan演算法)演算法
- Tarjan演算法(強連通分量分解)演算法
- 無向連通圖點雙連通分量
- 強連通分量
- 圖論——強連通分量(Tarjan演算法)圖論演算法
- 「學習筆記」雙連通分量、割點與橋筆記
- 強連通------tarjan演算法詳解及與縮點聯合運用演算法
- kosaraju 和 tarjan演算法詳解(強連通分量)演算法
- Tarjan求強連通分量
- UVA1327 && POJ1904 King's Quest(tarjan+巧妙建圖+強連通分量+縮點)
- Day7 割點、割邊和強連通分量
- 強化學習之路一 QLearning 演算法強化學習演算法
- POJ 1236 Network of Schools 強連通分量
- 無向連通圖邊雙連通分量
- 尋找圖的強連通分量:tarjan演算法簡單理解演算法
- 有向圖的強連通分量 模版
- 20行程式碼實現,使用Tarjan演算法求解強連通分量行程演算法
- Tarjan 求有向圖的強連通分量
- UVA-11504 - Dominos(有向圖的強連通分量)
- 強聯通分量tarjan
- OceanBase學習之路3 |SpringJDBC 連線示例SpringJDBC
- OceanBase學習之路4|SpringBoot 連線示例Spring Boot
- OceanBase學習之路9|連線方式概述
- Tarjan演算法_縮點演算法
- 強化學習-學習筆記15 | 連續控制強化學習筆記
- 邊分治維護強連通分量(CF1989F,P5163)
- Day8 雙連通分量
- 小白機器學習基礎演算法學習必經之路(下)機器學習演算法
- 深度學習影象視訊壓縮演算法——TNG深度學習演算法
- 抓間諜(強連通)
- 強化學習(十七) 基於模型的強化學習與Dyna演算法框架強化學習模型演算法框架
- 演算法學習之旅,終點亦是起點演算法
- tarjan演算法求scc & 縮點演算法
- OceanBase學習之路14|體驗並行匯入 & 資料壓縮並行
- 強化學習演算法筆記之【DDPG演算法】強化學習演算法筆記