強連通分量模板
阿新 • • 發佈:2019-02-04
【題目描述】
給出一個有向圖有n個點和m條有向邊,輸出連通分量的數量。
概念:
1. 什麼是連通分量?
答:一個有向圖中,選出某些點組成一個團體,這個團體中的任意兩點都可互相到達。那麼:選出來的這些點+這些點之間原有的邊=叫做 連通分量。
2. 只適合有向圖
答:如果是無向圖,那麼並查集就可以解決了(還記得“家族”嗎?)
附加1:什麼是強連通圖?
答:如果有向圖G的任意兩個頂點都可以互相到達,稱G是一個強連通圖。
附加2:什麼是強連通分量?
答:比如GG是G的最大的強連通子圖,稱為G的強連通分量(可能不止一個,這個不重要)
比如輸入樣例1,有3個連通分量:(1)、(2,3,4,5,6)、(7)
比如輸入樣例2,有3個連通分量:(1,2,3)、(4,6,7)、(5)
【輸入格式】
第一行n和m(1<=n<=20000,1<=m<=20 0000),表示有向圖總共n個點,點的編號由1~n。m表示m條有向邊。
下來m行,每行兩個整數x和y,表示一條有向邊從點x出發到點y。
【輸出格式】
一行一個整數,表示連通分量的個數。
【樣例1輸入】
7 7
1 2
2 3
3 4
4 5
5 6
6 2
5 2
【樣例1輸出】
3
【樣例2輸入】
7 11
1 2
1 4
2 3
2 5
3 1
3 5
3 6
4 6
5 7
6 7
7 4
【樣例2輸出】
3
#include<cstdio> using namespace std; struct edge{int to,next;}a[200001]; int n,m,dfn[20001],low[20001],h[20001],dx,line[20001],top,ans; bool bo[20001]; void dfs(int x) { dfn[x]=low[x]=++dx; line[++top]=x; bo[x]=true; int y; for (int i=h[x];i;i=a[i].next) { y=a[i].to; if (!dfn[y]) { dfs(y); if (low[y]<low[x]) low[x]=low[y]; } else if (bo[y]&&dfn[y]<low[x]) low[x]=dfn[y]; } if (dfn[x]==low[x]) { y=0; ans++; while (x!=y) { y=line[top--]; bo[y]=false; } } } int main() { scanf("%d%d",&n,&m); int x,y; for (int i=1;i<=m;i++) { scanf("%d%d",&x,&y); a[i].to=y; a[i].next=h[x]; h[x]=i; } for (int i=1;i<=n;i++) if (!dfn[i]) dfs(i); printf("%d",ans); return 0; }