• Tarjan算法——强连通分量


    ´Tarjan算法是一个通过对图进行深度优先搜索并通过同时维护一个栈以及两个相关时间戳的算法。
    ´定义dfn(u)表示节点u搜索的次序编号(时间戳,第几个搜索的节点),low(u)表示节点u或u的子树当中可以找到的最早的栈中的节点的时间戳。
     
    ´由定义,我们可以得到:
    ´Low(u)=dfn(u),
    ´low(u)=min(low(u),low(v))当(u,v)为搜索树当中的树枝边。
    ´low(u)=min(low(u),dfn(v))当(u,v)为搜索树当中的后向边(也就是v仍在栈内的情况)
    ´每当找到一个节点在遍历完后返回时low(u)=dfn(u),那么可以弹出栈中u以上的所有节点,此时这里的所有节点形成一个强连通分量
     
    缩点操作:
    ´当我们在求出强连通分量之后,我们可以把同一个强连通分量里的点当成新图里的一个新点,然后如果原图中两个不在同一个强连通分量的点有连边的话,那么他们所对应的新点也有连边。
    ´我们可以知道,新图一定是一个有向无环图。
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn=100000+15;
     5 const int maxm=100000+15;
     6 struct Edge
     7 {
     8     int x,y,next;
     9     Edge(int x=0,int y=0,int next=0):x(x),y(y),next(next) {} 
    10 }edge[maxm];
    11 int sumedge,head[maxn]; 
    12 int n,m;
    13 int ins(int x,int y)
    14 {
    15     edge[++sumedge]=Edge(x,y,head[x]);
    16     return head[x]=sumedge;
    17 }
    18 int tim,dfn[maxn],low[maxn],Stack[maxn],top,color[maxn],sumc;
    19 int state[maxn];
    20 int dfs(int now)
    21 {
    22     state[now]=1;
    23     dfn[now]=++tim;
    24     low[now]=dfn[now];
    25     Stack[++top]=now;
    26     for (int u=head[now];u;u=edge[u].next)
    27      if (state[edge[u].y]==0)
    28      {
    29          dfs(edge[u].y);
    30          low[now]=min(low[now],low[edge[u].y]);
    31       } 
    32       else 
    33       if (state[edge[u].y]==1)
    34        low[now]=min(low[now],dfn[edge[u].y]);
    35     if (dfn[now]==low[now])
    36     {
    37         sumc++;
    38         for (;Stack[top]!=now;top--)
    39         {
    40             color[Stack[top]]=sumc;
    41             state[Stack[top]]=2;
    42         }
    43         color[now]=sumc;
    44         state[now]=2;
    45         top--;
    46     }
    47     return 0;
    48 }
    49 int main()
    50 {
    51     scanf("%d%d",&n,&m);
    52     for (int i=1;i<=m;i++)
    53     {
    54         int x,y;
    55         scanf("%d%d",&x,&y);
    56         ins(x,y); 
    57     } 
    58     dfs(1);
    59     for (int i=1;i<=n;i++) printf("%d ",color[i]);
    60     printf("
    ");
    61     return 0;
    62  } 
  • 相关阅读:
    变量、内存区域、MDK文件(map、htm)
    全双工与半双工的区别
    4G网络 LTE、 FDD 和TD网络格式区别
    国内4G频段划分
    Nordic老版官网介绍(2018-11-30停止更新)
    无线通信模组产业链及竞争格局分析
    LBS 与 GPS 定位之间的区别
    99%的人都理解错了HTTP中GET与POST的区别(转自知乎)
    goto 的用法
    C语言字节对齐 __align(),__attribute((aligned (n))),#pragma pack(n)
  • 原文地址:https://www.cnblogs.com/9pounds15pence/p/6349701.html
Copyright © 2020-2023  润新知