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就够了

  • 相关阅读:
    小程序的目录结构及基本代码编写流程
    vue+hbuilder监听安卓返回键问题
    VUE项目用hbuilder 打包为手机APP
    VUE组件相关总结!
    VUE常用指令总结!
    vue开发者工具vue-devtools-4.1.4_0.crx谷歌插件下载及安装
    vue-cli环境搭建初探!
    PHP返回Json数据函数封装
    WeX5入门之HelloWorld
    WeX5入门之欢乐捕鱼打包
  • 原文地址:https://www.cnblogs.com/aininot260/p/9427601.html
Copyright © 2011-2022 走看看