tarjan算法_Tarjan算法求割点

 海绵宝宝与派大星的算法题解:第二篇

Tarjan用于求割点

01

洛谷 P3388 【模板】割点(割顶)

P1195 口袋的天

753c6570a1b0a31e4d217e1a5481135e.png

      思路:用两个数组来记录访问的序号,dfn[u]表示第一次访问到u节点的顺序,low[u]表示通过子节点可以回溯到的最小顺序,如果非根节点可通过子节点更新的low[u]小于它本身及有回路,反之无回路。当[u]结点是根节点,且有两棵及以上子树时其必是割点。

#includeusing namespace std;struct node{  int nxt,mark;}pre[200020];int n,m,idx,cnt,tot;int head[200020],dfn[200020],low[200020];bool cut[200020];void add(int u,int v){  pre[++cnt].nxt=v;  pre[cnt].mark=head[u];  head[u]=cnt;}void tarjan(int u,int fa){  dfn[u]=low[u]=++idx;  int child=0;  for(int i=head[u];i!=0;i=pre[i].mark){    int nx=pre[i].nxt;    if(!dfn[nx]){      tarjan(nx,fa);      low[u]=min(low[u],low[nx]);//重点      if(low[nx]>=dfn[u]&&u!=fa)        cut[u]=1;      if(u==fa)        child++;    }    low[u]=min(low[u],dfn[nx]);//重点 不能为low[u]=min(low[u],low[nx]) 8字形时错误  }  if(child>=2&&u==fa)    cut[u]=1;}int main(){  scanf("%d%d",&n,&m);  for(int i=1;i<=m;i++){    int a,b;    scanf("%d%d",&a,&b);    add(a,b);    add(b,a);  }  for(int i=1;i<=n;i++)    if(!dfn[i])      tarjan(i,i);  for(int i=1;i<=n;i++)    if(cut[i])      tot++;  printf("%d\n",tot);  for(int i=1;i<=n;i++)    if(cut[i])      printf("%d ",i);  return 0;}

f60641b8671780b52f757744a0e8e44a.png

与君共勉

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值