在一个有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强联通。
如果所有顶点都强联通,称G是一个强联通图。
非强联通图有向图的极大强联通子图,称为强联通分量。
深度优先搜索。
DFN(i):节点i被搜索到的次序编号。
LOW(i):i或i的子树能够追溯到的最早的节点的次序号。
LOW I = min ( dfn i , low j , dfn j)
当DFN i = LOW i 以 i 为根的的子树上所有节点是一个强联通分量。
时间复杂度:O(N+M)
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include <bits/stdc++.h> 6 using namespace std; 7 typedef long long ll; 8 const ll mod=998244353; 9 const int N=1e5+100; 10 const int maxn=1e6; 11 const int MAXL=sqrt(1e14)+1; 12 inline int read() { 13 char c = getchar(); int x = 0, f = 1; 14 while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} 15 while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); 16 return x * f; 17 } 18 int n,m; 19 int Link[N],len=0,dfn[N],low[N],bok[N]; 20 int belong[N],id,bcnt; 21 stack<int>s; 22 struct node 23 { 24 int y,next; 25 }e[2*N]; 26 void insert(int xx,int yy) 27 { 28 e[++len].next=Link[xx]; 29 Link[xx]=len; 30 e[len].y=yy; 31 } 32 void targin(int x) 33 { 34 dfn[x]=low[x]=++id; 35 s.push(x); 36 bok[x]=1; 37 for(int i=Link[x];i;i=e[i].next) 38 { 39 int v=e[i].y; 40 if(!dfn[v]) 41 { 42 targin(v); 43 low[x]=min(low[x],low[v]); 44 } 45 else if(bok[v]) 46 { 47 low[x]=min(low[x],dfn[v]); 48 } 49 } 50 if(dfn[x]==low[x]) 51 { 52 bcnt++; 53 while(true) 54 { 55 int v=s.top(); 56 s.pop(); 57 bok[v]=0; 58 belong[v]=bcnt; 59 if(x==v) break; 60 } 61 } 62 63 } 64 int solve() 65 { 66 n=read(); m=read(); 67 int xx,yy; 68 for(int i=1;i<=m;i++) 69 { 70 xx=read(); yy=read(); 71 insert(xx,yy); 72 } 73 for(int i=1;i<=n;i++) 74 if(!dfn[i]) 75 targin(i); 76 77 78 } 79 80 81 int main() 82 { 83 int T=1; 84 scanf("%d",&T); 85 //T=1; 86 //cout<<tot<<endl; 87 int tt=0; 88 while(T--) 89 90 { 91 //if(n==0) break; 92 //printf("Case %d: ",++tt); 93 solve(); 94 } 95 96 return 0; 97 98 }
缩点:
for(int i=1;i<=n;i++) { for(int j=Link[i];j;j=e[i].next) { int v=e[j].y; if(belong[i]!=belong[v]) insert(belong[i],belong[v]); } }