• 强连通分量tarjan模板复习


    对于一个有向图定点的子集,在该子集中任取两点u与v,都能找到一条从u到v的路径,则称该子集是强连通的。若该集合加入到任意点集中,它都不再强连通,则称这个子集是原图的一个强连通分量。任意一张图都可以分解成若干个不相交的强连通分量。这是强连通分量分解。把分解后的强连通分量缩成一个顶点,就可以得到一个有向无环图。

    如图:

    求一张图的强连通分量的个数,常用tarjan算法,它是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树。搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断栈顶到栈中的节点是否为一个强连通分量。

    模板如下:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 int n,m;
     8 struct node{
     9     int fr,to;
    10 }ed[50001];
    11 bool vis[10001];
    12 int dfs[10001],stack[10001],head[10001],low[10005];
    13 int tot=0,ans=0,in=0,num=0;
    14 void add(int u,int v){
    15     ed[++num].fr=head[u];head[u]=num;ed[num].to=v;
    16 }
    17 void tarjan(int x){
    18     dfs[x]=low[x]=++tot;
    19     stack[++in]=x;
    20     vis[stack[in]]=1;
    21     int i;
    22     for(i=head[x];i;i=ed[i].fr){
    23         if(!dfs[ed[i].to]){
    24             tarjan(ed[i].to);
    25         }
    26         if(vis[ed[i].to]){
    27             low[x]=min(low[x],low[ed[i].to]);
    28         }
    29     }
    30     if(low[x]==dfs[x]){
    31         for(++ans;stack[in+1]!=x;)  vis[stack[in--]]=0;
    32     }
    33 }
    34 int main(){
    35     scanf("%d%d",&n,&m);
    36     int i;
    37     for(i=1;i<=m;i++){
    38         int x,y;
    39         scanf("%d%d",&x,&y);
    40         add(x,y);
    41     }
    42     for(i=1;i<=n;i++)  if(!dfs[i])  tarjan(i);
    43     printf("%d\n",ans);
    44     return 0;
    45 }
  • 相关阅读:
    BZOJ1217: [HNOI2003]消防局的设立
    BZOJ3925: [Zjoi2015]地震后的幻想乡
    BZOJ2328: [HNOI2011]赛车游戏
    BZOJ1011: [HNOI2008]遥远的行星
    BZOJ2007: [Noi2010]海拔
    BZOJ1833: [ZJOI2010]count 数字计数
    BZOJ1026: [SCOI2009]windy数
    BZOJ1196: [HNOI2006]公路修建问题
    BZOJ1076: [SCOI2008]奖励关
    BZOJ2752: [HAOI2012]高速公路(road)
  • 原文地址:https://www.cnblogs.com/lazytear/p/6890341.html
Copyright © 2020-2023  润新知