tarjan

作者: 雨落八千里 | 来源:发表于2019-06-12 20:56 被阅读4次

tarjan寻找出度为0的强连通分量,从小到大输出此强连通分量中的点

poj 2553 The Bottom of a Graph
图存在多个强连通分量,强连通分量内的所有点的行为可以压缩为一个点的行为:若强连通分量的一个点可以到达其他强连通分量,则该强连通分量内的所有点均可以到达其他强连通分量;若强连通分量可以被其他强连通分量的点到达,则该强连通分量内的所有点均可以被其他强连通分量的点到达。因此,将图的强连通分量缩成一个点是一个经常会进行的操作。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
#include<stack>
#define M 5500
using namespace std;
int dfn[M],low[M];
int tot,sig,n,m;
int vis[M];
int col[M];
int dep[M];
stack<int>s;
vector<int>vep[M];
void init( )
{
      tot=sig=0;
      memset(dep,0,sizeof(dep));
      memset(vis,0,sizeof(vis));
      memset(dfn,0,sizeof(dfn));
      memset(low,0,sizeof(low));
      for(int i=0;i<M;i++)
      {
            vep[i].clear( );
      }
}
void tarjan(int x)
{
      dfn[x]=low[x]=++tot;
      s.push(x);
      vis[x]=1;
      for(int i=0;i<vep[x].size( );i++)
      {
            int j=vep[x][i];
            if(!dfn[j])
            {
                  tarjan(j);
                  low[x]=min(low[x],low[j]);
            }
            else if(vis[j])
            {
                  low[x]=min(low[x],dfn[j]);
            }
      }
      if(dfn[x]==low[x])
      {
            sig++;//连通分量个数
            int k;
            do
            {
                  k=s.top( );
                  vis[k]=0;
                  col[k]=sig;//每个点属于那个连通分量
                  s.pop( );
            }while(x!=k);
      }
      return ;
}
void solve(int n)
{
      for(int i=1;i<=n;i++)
      {
            if(!dfn[i])
            {
                  tarjan(i);
            }
      }
      //cout<<sig<<endl;
      for(int i=1;i<=n;i++)
      {
            for(int j=0;j<vep[i].size( );j++)
            {
                  int v=vep[i][j];
                  if(col[i]!=col[v])
                  {
                        dep[col[i]]++;//每个点对应的连通分量的出度
                  }
            }
      }
      for(int i=1;i<=n;i++)
      {
            if(dep[col[i]]==0)
            {
                  cout<<i<<" ";
            }
      }
      cout<<endl;
      return ;
}
int main( )
{
      int x,y;
      while(cin>>n>>m&&n)
      {
            init( );
            for(int i=1;i<=m;i++)
            {
                  cin>>x>>y;
                  vep[x].push_back(y);
            }
            solve(n);

      }
      return 0;
}

相关文章

  • tarjan

    tarjan缩点的运用,寻找一个较小的点集使得从这些点出发能够到达任意不在点集中的点,若有多个点,输出这些集合升序...

  • tarjan

    tarjan:寻找出度为0的强连通分量,并求出该强连通分量中有多少个点。 sig表示的是强连通分量的个数其中col...

  • tarjan

    tarjan寻找出度为0的强连通分量,从小到大输出此强连通分量中的点 poj 2553 The Bottom of...

  • Tarjan学习笔记

    在最近学习中遇到了几次题解使用Tarjan的情况,便查了一些资料。 算法简介 一种由Robert Tarjan提出...

  • tarjan算法

    tarjan算法前提 一个关于图的联通性的神奇算法。基于DFS(深度搜索)算法,深度优先搜索一张有向图。!注意!是...

  • 连通图

    Strongly Connected Componenet 割点(tarjan): 题目链接:Network(求割...

  • tarjan算法动态演示

    java swing写的tarjan算法[https://zhuanlan.zhihu.com/p/1019233...

  • 图算法(二)Tarjan

    在一次BFS或DFS中,我们其实并不能保证一定访问到图中的所有节点,因为有些图可能是不连通的。我们把从一个点出发,...

  • 强连通tarjan模版

    时间复杂度为O(n+m) 黑匣子: 先最初调用 1、init() 2、把图用add 存下来,注意图点标为1-n,若...

  • 刷题计划

    并查集 题目 图论 题目 树 题目 资源参考 倍增LCA LCA和RMQ Tarjan LCA 倍增 题目 DP 题目

网友评论

    本文标题:tarjan

    本文链接:https://www.haomeiwen.com/subject/tpvrfctx.html