zoukankan      html  css  js  c++  java
  • 图论:割点

    Luogu3388:利用Tarjan求无向图的割点

    割点就是维护双连通分量的一个点,如果删去的话,原本的双连通分量就会被拆成若干个连通分量

    利用Tarjan算法可以求出无向图的所有割点

    下面介绍一下:

    int n,m,cnt,deep,root,ans;
    int g[maxn],dfn[maxn],low[maxn],iscut[maxn];
    struct Edge{int t,w,next;}e[maxm];

    邻接表建图,开二倍边长(无向图)

    deep用来跟踪记录每一个点的深度,或者说,它在dfs中是第几个访问的

    然后root是用来给当前进行dfs的连通分量指定的一个根

    dfn数组用来记录当前点在dfs中是第几个被搜到的,low数组用来记录这个点及其子孙节点所连的所有节点中,dfn的最小值

    由于本题不用求强连通分量,不用开栈记录了

    iscut的意思很显然

        for(int i=1;i<=n;i++)
            if(!dfn[i]) {root=i;tarjan(i,-1);}

    建图后对于每一个连通分量,进行一次Tarjan求割点

    Tarjan算法如下:

    int tarjan(int u,int fa)
    {
        int child=0,lowu;
        lowu=dfn[u]=++deep;
        for(int tmp=g[u];tmp;tmp=e[tmp].next)
        {
            int v=e[tmp].t;
            if(!dfn[v])
            {
                child++;
                int lowv=tarjan(v,u);
                lowu=min(lowu,lowv);
                if(lowv>dfn[u]) iscut[u]=1;
            }
            else if(v!=fa&&dfn[v]<dfn[u])
                lowu=min(lowu,dfn[v]);
        }
        if(fa<0&&child==1) iscut[u]=false;
        low[u]=lowu;
        return lowu;
    }

    具体原理和求强连通的Tarjan很类似(其实Tarjan就是一类东西。。。)

    先不介绍了以后再说

    下面给出完整的实现,题是洛谷上的一个板子题,然后我再洛谷上发现了不少神奇的板子,真是贴心

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 const int maxn=100005;
     5 const int maxm=200005;
     6 int n,m,cnt,deep,root,ans;
     7 int g[maxn],dfn[maxn],low[maxn],iscut[maxn];
     8 struct Edge{int t,w,next;}e[maxm];
     9 void addedge(int u,int v,int w)
    10 {
    11     e[++cnt].t=v;e[cnt].w=w;
    12     e[cnt].next=g[u];g[u]=cnt;
    13 }
    14 int tarjan(int u,int fa)
    15 {
    16     int child=0,lowu;
    17     lowu=dfn[u]=++deep;
    18     for(int tmp=g[u];tmp;tmp=e[tmp].next)
    19     {
    20         int v=e[tmp].t;
    21         if(!dfn[v])
    22         {
    23             child++;
    24             int lowv=tarjan(v,u);
    25             lowu=min(lowu,lowv);
    26             if(lowv>dfn[u]) iscut[u]=1;
    27         }
    28         else if(v!=fa&&dfn[v]<dfn[u])
    29             lowu=min(lowu,dfn[v]);
    30     }
    31     if(fa<0&&child==1) iscut[u]=false;
    32     low[u]=lowu;
    33     return lowu;
    34 }
    35 int main()
    36 {
    37     scanf("%d%d",&n,&m);
    38     int u,v;
    39     for(int i=1;i<=m;i++)
    40     {
    41         scanf("%d%d",&u,&v);
    42         addedge(u,v,1);addedge(v,u,1);
    43     }
    44     for(int i=1;i<=n;i++)
    45         if(!dfn[i]) {root=i;tarjan(i,-1);}
    46     for(int i=1;i<=n;i++)
    47         if(iscut[i]) ans++;
    48     printf("%d
    ",ans);
    49     for(int i=1;i<=n;i++)
    50         if(iscut[i]) printf("%d ",i);
    51     return 0;
    52 }

    目前的程度,先能调用API就够了

  • 相关阅读:
    HDU4529 郑厂长系列故事——N骑士问题 —— 状压DP
    POJ1185 炮兵阵地 —— 状压DP
    BZOJ1415 聪聪和可可 —— 期望 记忆化搜索
    TopCoder SRM420 Div1 RedIsGood —— 期望
    LightOJ
    LightOJ
    后缀数组小结
    URAL
    POJ3581 Sequence —— 后缀数组
    hdu 5269 ZYB loves Xor I
  • 原文地址:https://www.cnblogs.com/aininot260/p/9427601.html
Copyright © 2011-2022 走看看