有向图的强连通分量分解

首先明白什么是强连通分量(SCC),然后考虑把有向图中的强连通分量缩成一个顶点,就得到了一个DAG(有向无环图),这就是强连通分量分解。

korasaju算法实现:通过两次DFS,第一次任取顶点作为起点,遍历所有未访问过的顶点,并在回溯前给顶点标号(后序遍历),对剩余未访问过的顶点,不断重复上述过程;

第二次DFS时,先将所有边反向,然后以标号最大的顶点为起点进行DFS,这样DFS所遍历的顶点集合就构成了一个强连通分量,对剩余未访问过的顶点,不断重复上述过程。

ps:反向后强连通的集合,还是强连通的。


时间复杂度:O(E+V)

其他分解算法:tarjan算法,Gabow算法


代码:

int V;//顶点数
vector<int> G[max_v];//图的邻接表表示
vector<int> rG[max_v];//图的逆邻接表表示
vector<int> vs;//后续遍历顺序的顶点列表
bool used[max_v);//访问标记
int cmp[max_v];//所属强连通分量的拓扑序

void add_edge(int from,int to)
{
          G[from].push_back(to);
          rG[to].push_back(from);
}

void dfs(int v)
{
         used[v]=true;
         for(int i=0;i<G[v].size();i++)
                  if(!used[G[v][i]])
                            dfs(G[v][i]);
         vs.push_back(v);
}

void rdfs(int v,int k)
{
          used[v]=true;
          cmp[v]=k;
          for(int i=0;i<rG[v].size();i++)
                     if(!used[rG[v][i]])
                                rdfs(rG[v][i],k);
}

int scc()//返回强连通分量个数
{
          memset(used,0,sizeof(used));
          vs.clear();
          for(int v=0;v<V;v++)
                     if(!used[v[)
                                 dfs(v);
          memset(used,0,sizeof(used));
          int k=0;
          for(int i=vs.size()-1;i>=0;i--)
                    if(!used[vs[i]])
                                 rdfs(vs[i],k++);
          return k;
}


                   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值