其他分享
首页 > 其他分享> > [图论]强联通分量

[图论]强联通分量

作者:互联网

暂时不知道这玩意怎么用,暂时不知道啥时候用这玩意....

在有向图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