tarjan求割点和桥(割边)

2 篇文章 0 订阅
1 篇文章 0 订阅

tarjan求割点和桥

参考博客:tarjan求割点和桥(割边)

例题:割点

代码(重要的地方在代码中都有注释):

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const ll M=2e4+10,maxn=3e6+30;

int dfn[M],low[M],tot;
int e[M<<1],k,p[M],k2;
vector<int> g[M];

void tarjan(int x,int f)
{
    dfn[x]=low[x]=++tot;
    int son=0;
    bool flag=false;
    for(int i=0;i<g[x].size();i++)
    {
        int v=g[x][i];
        if(!dfn[v])
        {
            son++;
            tarjan(v,x);
            if(low[v]>=dfn[x])flag=true;
            if(low[v]>dfn[x])//判断桥(割边)
            {
                e[k++]=x;
                e[k++]=v;
            }
            low[x]=min(low[x],low[v]);
        }
        else if(v!=f)low[x]=min(low[x],dfn[v]);
        //一条无向边实际在g中对应两条有向边,不能通过反向边更新到父节点之上
    }
    //割点:1.不是根节点满足low[v]>=dfn[x] 2.是根节点且有两个以上的子树
    if(flag&&f||f==0&&son>1)p[k2++]=x;
}

int main()
{
    freopen("hello.txt","r",stdin);
    int n,m;
    scanf("%d%d",&n,&m);
    int x,y;
    while(m--)
    {
        scanf("%d%d",&x,&y);
        g[x].push_back(y);
        g[y].push_back(x);
    }
    for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i,0);

    for(int i=0;i<k;)
    {
        printf("<%d,",e[i++]);
        printf("%d> ",e[i++]);
    }
    printf("\n");
    for(int i=0;i<k2;i++)i==k2-1?printf("%d\n",p[i]):printf("%d ",p[i]);

    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值