Tarjan算法

具体算法:http://hi.baidu.com/z917912363/item/a489943f63b27a5680f1a777

http://acm.hdu.edu.cn/showproblem.php?pid=1269

#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;



struct{

      int to,next;

}edge[100005];    //边结点数组



int head[10010],stack[10010],DFN[10010],Low[10010],Belong[100010];

//  head[]头结点数组,stack[]为栈,DFN[]为深搜次序数组,Belong[]为每个结点所对应的强连通分量标号数组

 //      Low[u]为u结点或者u的子树结点所能追溯到的最早栈中结点的次序号

int instack[10010],cnt,scnt,top,n,tot;

// instack[]为是否在栈中的标记数组



void Add(int x,int y){    //构建邻接表

     edge[tot].to=y;

     edge[tot].next=head[x];

     head[x]=tot++;

}



void Tarjan(int v)       //Tarjan算法求有向图的强连通分量

{

     int min,i,t,j;

     DFN[v]=Low[v]=++cnt;    //cnt为次序计数器

     instack[v]=1;    //标记在栈中

     stack[top++]=v;      //入栈

     for(i=head[v];i!=-1;i=edge[i].next){   //枚举v的每一条边

           j=edge[i].to;   //v所邻接的边

           if(!DFN[j]){   //未被访问

               Tarjan(j);    //继续向下找

               if(Low[v]>Low[j])Low[v]=Low[j];  // 更新结点v所能到达的最小次数层

           }else if(instack[j]&&DFN[j]<Low[v]){   //如果j结点在栈内,

               Low[v]=DFN[j];

           }

     }

     if(DFN[v]==Low[v]){     //如果节点v是强连通分量的根

           scnt++;   //连通分量标号加1

           do{

               t=stack[--top];   //退栈

               instack[t]=0;   //标记不在栈中

               Belong[t]=scnt;   //出栈结点t属于cnt标号的强连通分量

           }while(t!=v);  //直到将v从栈中退出

     }

}



void Slove(){

     int i;

     scnt=cnt=top=0;    //初始化连通分量标号,次序计数器,栈顶指针为0

     memset(DFN,0,sizeof(DFN));    //结点搜索的次序编号数组为0,同时可以当是否访问的数组使用

     for(i=1;i<=n;i++)   //枚举每个结点,搜索连通分量

        if(!DFN[i])  //未被访问

           Tarjan(i);  //则找i结点的连通分量

}



int main(){

    int m,i,x,y;

    while(scanf("%d%d",&n,&m),n+m){

           memset(head,-1,sizeof(head));   //邻接表的头结点数组初始化为-1

           while(m--){

               scanf("%d%d",&x,&y);

               Add(x,y);

           }

           Slove();     //求强连通分量

           if(scnt==1)       //只有一个强连通分量,说明此图各个结点都可达

              printf("Yes
");

           else

              printf("No
");

    }

}
View Code
原文地址:https://www.cnblogs.com/lyf123456/p/3703857.html