zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    函数配接器
    函数对象和函数指针
    unary_function 和 binary_function
    堆排序
    Shell排序
    volatile理解
    死锁
    进程间通信
    优化循环的方法-循环展开
    如何学习编译原理
  • 原文地址:https://www.cnblogs.com/lyf123456/p/3703857.html
Copyright © 2011-2022 走看看