zoukankan      html  css  js  c++  java
  • Tarjan模版(链式向前星表示方法)

    这道模版用到了链式向前星表示法:

     struct node 
     {  
         int v,next;  
     }edge[1001];  
    
    void add(int x,int y)  
    {  
         edge[++cnt].next=heads[x];  
         edge[cnt].v = y;  
         heads[x]=cnt;  
        return ;  
     }  

    有地方写错了,应该是i=edge[i].next

    输入:
    一个图有向图。
    输出:
    它每个强连通分量。

    input:

    6 8

    1 3

    1 2

    2 4

    3 4

    3 5

    4 6

    4 1

    5 6

    output:

    6

    5

    3 4 2 1

     #include<cstdio>  
     #include<algorithm>  
     #include<string.h>  
     using namespace std;  
     struct node 
     {  
         int v,next;  
     }edge[1001];  
      
     int DFN[1001],LOW[1001];  
     int stack[1001],heads[1001],visit[1001],cnt,tot,index; 
    
    void add(int x,int y)  
    {  
         edge[++cnt].next=heads[x];  
         edge[cnt].v = y;  
         heads[x]=cnt;  
        return ;  
     }  
    
     void tarjan(int x)//代表第几个点在处理。递归的是点。  
     {  
         DFN[x]=LOW[x]=++tot;// 新进点的初始化。  
         stack[++index]=x;//进站  
         visit[x]=1;//表示在栈里  
        for(int i=heads[x];i!=-1;i=edge[i].next)  
         {  
             if(!DFN[edge[i].v])
             {//如果没访问过  
                tarjan(edge[i].v);//往下进行延伸,开始递归  
                 LOW[x]=min(LOW[x],LOW[edge[i].v]);//递归出来,比较谁是谁的儿子/父亲,就是树的对应关系,涉及到强连通分量子树最小根的事情。  
            }  
            else if(visit[edge[i].v ])
            {  //如果访问过,并且还在栈里。  
                 LOW[x]=min(LOW[x],DFN[edge[i].v]);//比较谁是谁的儿子/父亲。就是链接对应关系  
             }  
         }  
         if(LOW[x]==DFN[x]) //发现是整个强连通分量子树里的最小根。  
        {  
             do
             {  
                printf("%d ",stack[index]);  
                 visit[stack[index]]=0;  
                 index--;  
             }
             while(x!=stack[index+1]);//出栈,并且输出。  
             printf("
    ");  
         }  
         return ;  
     }  
     int main()  
     {  
         memset(heads,-1,sizeof(heads));  
         int n,m;  
         scanf("%d%d",&n,&m);  
        int x,y;  
         for(int i=1;i<=m;i++)  
         {  
             scanf("%d%d",&x,&y);  
            add(x,y);  
         }  
        for(int i=1;i<=n;i++)  
             if(!DFN[i])  tarjan(i);//当这个点没有访问过,就从此点开始。防止图没走完  
        return 0;  
     }  
  • 相关阅读:
    19.02.11——周记
    假期第一周
    JavaWeb——升级赛-学生成绩管理系统(2).java---19.01.03
    JavaWeb——升级赛-学生成绩管理系统(1)jsp---19.01.03
    构建之法阅读笔记02
    输出一个数组里最大子数组的和(文件)
    软件工程第二周总结
    软件工程第一周开课博客
    构建之法阅读笔记01
    返回一个整数数组中最大子数组的和
  • 原文地址:https://www.cnblogs.com/caiyishuai/p/8536797.html
Copyright © 2011-2022 走看看