[图论]强联通分量
作者:互联网
暂时不知道这玩意怎么用,暂时不知道啥时候用这玩意....
在有向图G中,如果两点互相可达,则称这两个点强连通,如果G中任意两点互相可达,则称G是强连通图。
定理: 1、一个有向图是强连通的,当且仅当G中有一个回路,它至少包含每个节点一次。
2、非强连通有向图的极大强连通子图,称为强连通分量(SCC即Strongly Connected Componenet)。
怎么求这个强联通分量呢?
Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树。总的来说, Tarjan算法基于一个观察,即:同处于一个SCC中的结点必然构成DFS树的一棵子树。 我们要找SCC,就得找到它在DFS树上的根。
-----------------------------------------------------------------------------------
tin[u]代表访问u节点的时间戳,low[u]代表u为根节点的dfs树中时间戳最小的顶点的时间戳。
访问到u时,tin[u]=low[u]=++id;
u入栈。
由u的顶点找下点v。若v未访问过,dfs(v); low[u]=min(low[u],low[v]);
若v已经访问过,则说明形成了环, low[u]=min(low[u],tin[v]);
若tin[u]==low[u] 则开始出栈,一直出到u。其中 用belong数组来记录这个点属于的块。
1 void tarjan(int u) 2 { 3 tin[u]=low[u]=++id; 4 s.push(u); 5 bok[u]=1; 6 for(int i=Link[u];i;i=e[i].next) 7 { 8 int v=e[i].y; 9 if(!tin[v]) 10 { 11 tarjan(v); 12 low[u]=min(low[u],low[v]); 13 } 14 else if(bok[v]) 15 { 16 low[u]=min(low[u],tin[v]); 17 } 18 } 19 if(tin[u]==low[u]) 20 { 21 Bcnt++; 22 while(true) 23 { 24 int v=s.top(); 25 s.pop(); 26 bok[v]=0; 27 belong[v]=Bcnt; 28 if(u==v) break; 29 } 30 } 31 }View Code
1 for(int i=1;i<=n;i++) 2 if(!tin[i]) 3 tarjan(i); 4 int f=1; 5 for(int i=1;i<=n;i++) 6 if(belong[i]!=1) 7 f=0; 8 if(f) printf("Yes\n"); 9 else printf("No\n");View Code
标签:图论,有向图,联通,min,int,连通,tin,low,分量 来源: https://www.cnblogs.com/Kaike/p/11143930.html