zoukankan      html  css  js  c++  java
  • 强连通分量(Tarjan)模板

    贴模板,备忘。

    模板1:

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cmath>
     4 #include<cstdlib>
     5 #include<cstdio>
     6 #include<algorithm>
     7 #include<string.h>
     8 using namespace std;
     9 struct node {
    10     int v,next;
    11 }edge[1001];
    12 int DFN[1001],LOW[1001];
    13 int stack[1001],heads[1001],visit[1001],cnt,tot,index;
    14 void add(int x,int y)
    15 {
    16      edge[++cnt].next=heads[x];
    17      edge[cnt].v = y;
    18      heads[x]=cnt;
    19      return ;
    20  }
    21 void tarjan(int x)//代表第几个点在处理。递归的是点。
    22 {
    23      DFN[x]=LOW[x]=++tot;// 新进点的初始化。
    24      stack[++index]=x;//进站
    25      visit[x]=1;//表示在栈里
    26      for(int i=heads[x];i!=-1;i=edge[i].next)
    27      {
    28          if(!DFN[edge[i].v]) {//如果没访问过
    29              tarjan(edge[i].v);//往下进行延伸,开始递归
    30              LOW[x]=min(LOW[x],LOW[edge[i].v]);//递归出来,比较谁是谁的儿子/父亲,就是树的对应关系,涉及到强连通分量子树最小根的事情。
    31          }
    32          else if(visit[edge[i].v ]){  //如果访问过,并且还在栈里。
    33              LOW[x]=min(LOW[x],DFN[edge[i].v]);//比较谁是谁的儿子/父亲。就是链接对应关系
    34          }
    35      }
    36      if(LOW[x]==DFN[x]) //发现是整个强连通分量子树里的最小根。
    37      {
    38          do{
    39              printf("%d ",stack[index]);
    40              visit[stack[index]]=0;
    41              index--;
    42          }while(x!=stack[index+1]);//出栈,并且输出。
    43          printf("
    ");
    44      }
    45      return ;
    46 }
    47 int main()
    48 {
    49      memset(heads,-1,sizeof(heads));
    50      int n,m;
    51      scanf("%d%d",&n,&m);
    52      int x,y;
    53      for(int i=1;i<=m;i++)
    54      {
    55          scanf("%d%d",&x,&y);
    56         add(x,y);
    57      }
    58      for(int i=1;i<=n;i++)
    59          if(!DFN[i])  tarjan(i);//当这个点没有访问过,就从此点开始。防止图没走完
    60      return 0;
    61 }

    模板2:

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<queue>
     5 #include<stack>
     6 #define maxn 1005
     7 using namespace std;
     8 struct Edge
     9 {
    10     int next;
    11     int to;
    12 }edge[maxn];
    13 int head[maxn];
    14 int cnt;
    15 int step;
    16 int dfn[maxn];//表示深搜的步数;
    17 int low[maxn];//表示能追溯到最早的栈中节点的次序;
    18 int sccno[maxn];//缩点数组,表示每个点对应的缩点值;
    19 int scc_cnt;//强连通分量的个数;
    20 void init()
    21 {
    22     cnt=0;
    23     step=0;
    24     memset(head,-1,sizeof(head));
    25 }
    26 void add(int u,int v)
    27 {
    28     edge[cnt].next=head[u];
    29     edge[cnt].to=v;
    30     head[u]=cnt++;
    31 }
    32 vector<int>scc[maxn];//得出来的缩点,保存具体缩了那些点;
    33 stack<int>s;
    34 void dfs(int u)
    35 {
    36     dfn[u]=low[u]=++step;
    37     s.push(u);
    38     for(int i=head[u];i!=-1;i=edge[i].next)
    39     {
    40         int v=edge[i].to;
    41         if(!dfn[v])
    42         {
    43             dfs(v);
    44             low[u]=min(low[u],low[v]);
    45         }
    46         else if(!sccno[v])
    47         {
    48             low[u]=min(low[u],dfn[v]);
    49         }
    50     }
    51     if(low[u]==dfn[u])
    52     {
    53         scc_cnt++;
    54         scc[scc_cnt].clear();
    55         while(1)
    56         {
    57             int x=s.top();
    58             s.pop();
    59             if(sccno[x]!=scc_cnt)
    60                 scc[scc_cnt].push_back(x);
    61             sccno[x]=scc_cnt;
    62             if(x==u)
    63                 break;
    64         }
    65     }
    66 }
    67 void tarjan(int n)
    68 {
    69     memset(sccno,0,sizeof(sccno));
    70     memset(dfn,0,sizeof(dfn));
    71     step=scc_cnt=0;
    72     for(int i=1;i<=n;i++)
    73         if(!dfn[i])dfs(i);
    74 }
    75 int main()
    76 {
    77     int n,m;
    78     int x,y;
    79     cin>>n>>m;
    80     init();
    81     while(m--)
    82     {
    83         cin>>x>>y;
    84         add(x,y);
    85     }
    86     tarjan(n);
    87     cout<<scc_cnt<<endl;
    88     return 0;
    89 }

    滚了。

  • 相关阅读:
    被@ResponseBoby注释的方法在拦截器的posthandle方法中设置cookie失效的问题
    python之异常处理
    python之url编码
    python之发送邮件
    python之使用request模块发送post和get请求
    python之小技巧积累
    python之sys.argv[]
    python之MD5加密
    python之os、sys和random模块
    python之time和datetime的常用方法
  • 原文地址:https://www.cnblogs.com/ZERO-/p/8612861.html
Copyright © 2011-2022 走看看