当前位置: 首页 > news >正文

tarjan进阶

一、边双连通分量

定义

若一个无向图中的去掉任意一条边都不会改变此图的连通性,即不存在桥,则称作边双连通图。一个无向图中的每一个极大边双连通子图称作此无向图的边双连通分量。

实际求法和强连通分量差不多,只是要注意由于一条无向边被分为两条有向边存储,所以在经过其中一条从u到达v之后不能再通过另一条边由v返回u。

代码

inline void tarjan(int x,int fa){
      dfn[x]=low[x]=++cnt;
      a.push(x);
      ist[x]=1;
      int wh=0;
      for(int i=0;i<v[x].size();i++){
            if(v[x][i]==fa&&!wh){
              wh=1;
              continue;
            }
          if(!dfn[v[x][i]]){
            tarjan(v[x][i],x);
            low[x]=min(low[x],low[v[x][i]]);
          }else if(ist[v[x][i]]){
            low[x]=min(low[x],dfn[v[x][i]]);
          }
        }
      if(dfn[x]==low[x]){
          sum++;
          while(1){
            int u=a.top();
            a.pop();
            ist[u]=0;
            belong[u]=sum;
            if(u==x)break;
          }
      }
      return;
}

二、割点

定义

在一个无向图中,如果有一个顶点集合,删除这个顶点集合以及这个集合中所有顶点相关联的边以后,图的连通分量增多,就称这个点集为割点集合。

也就是说对于一条边的两个节点u和v,如果low[v]>=dfn[u]则u是一个割点(dfn[u]<dfn[v])。

代码

inline void tarjan(long long x,long long fa){
      dfn[x]=low[x]=++cnt;
      long long son=0;
      for(long long i=0;i<v[x].size();i++)
        if(v[x][i]!=fa){
          if(!dfn[v[x][i]]){
            son++;
            tarjan(v[x][i],x);
            low[x]=min(low[x],low[v[x][i]]);
            if(low[v[x][i]]>=dfn[x])is[x]=1;
          }else low[x]=min(low[x],dfn[v[x][i]]);
        }
      if(!fa&&son==1)is[x]=0;
      return;
}

三、桥

定义

是存在于无向图中的这样的一条边,如果去掉这一条边,那么整张无向图会分为两部分,这样的一条边称为桥无向连通图中,如果删除某边后,图变成不连通,则称该边为桥。

实际求法和割点差不多,就是要将条件dfn[u]<=low[v]改成dfn[u]<low[v]

代码

inline void tarjan(int x,int fa){
      int wh=0;
      dfn[x]=low[x]=++cnt;
      for(int i=0;i<v[x].size();i++)
        if(v[x][i]!=fa){
          if(!dfn[v[x][i]]){
              tarjan(v[x][i],x);
              low[x]=min(low[x],low[v[x][i]]);
              if(dfn[x]<low[v[x][i]])ans++;
          }else low[x]=min(low[x],dfn[v[x][i]]);
        }
      return;
}

以上是没有重边的情况,如果有则要这样写

代码

inline void tarjan(int x,int id){
      dfn[x]=low[x]=++T;
      for(int i=head2[x];i;i=nxt2[i])
        if((i+1)/2!=(id+1)/2){
          if(!dfn[to2[i]]){
              tarjan(to2[i],i);
              low[x]=min(low[x],low[to2[i]]);
              if(low[to2[i]]>dfn[x])is[id2[i]]=1,S++;;
          }else low[x]=min(low[x],dfn[to2[i]]);
        }
      return;
}

 

四、点双连通分量

定义

任意两个点之间存在至少两条点不重复路径。

实际上求点双是基于求割点的。我们每求到一个割点u便将之前栈里存储的点弹出,一直到v为止,注意要把u划到这个点双中但是不能将其弹出,因为一个割点可能属于多个点双。

代码(借用ttl的)

void tarjan(int x,int fa)
{
    dfn[x]=low[x]=++tarcnt;
    st[++tp]=x;
    for(int k=g1[x];k;k=e1[k].next)
    {
        int y=e1[k].to;if (y==fa) continue;
        if (dfn[y]==0)
        {
            tarjan(y,x);
            low[x]=min(low[x],low[y]);
            if (low[y]>=dfn[x]) 
            {
                int t;tot++;
                add(x,tot),add(tot,x);
                do {t=st[tp--],add(t,tot),add(tot,t);}while(t!=y);
            }
        }
        else low[x]=min(low[x],dfn[y]);
    }
}

转载于:https://www.cnblogs.com/yzxverygood/p/9525924.html

相关文章:

  • ubuntu13启动屏幕亮度0解决方法
  • 数据结构与抽象 Java语言描述 第4版 pdf (内含标签)
  • 文件尾存在EOF吗?
  • shell使用lftp连接ftp和sftp,并可以指定私钥
  • JMeter中的读取json数据---JSON Extractor插件
  • 添加GDataXMLNODE.h和.m的方法
  • Administrator 被禁用
  • 《Java8实战》-第四章读书笔记(引入流Stream)
  • 工作地址
  • Mysql系列七:分库分表技术难题之分布式全局唯一id解决方案
  • 2014年第一天
  • zabbix3.4 修改监控范围
  • poj1006_Biorhythms
  • JAVA自学笔记13
  • nginx根据访问的url参数或者是请求 头部做判断转发
  • 〔开发系列〕一次关于小程序开发的深度总结
  • 4. 路由到控制器 - Laravel从零开始教程
  • CSS实用技巧干货
  • eclipse(luna)创建web工程
  • Invalidate和postInvalidate的区别
  • iOS 系统授权开发
  • Python十分钟制作属于你自己的个性logo
  • 简单易用的leetcode开发测试工具(npm)
  • 前端临床手札——文件上传
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • 深入浅出Node.js
  • 与 ConTeXt MkIV 官方文档的接驳
  • 原生js练习题---第五课
  • Mac 上flink的安装与启动
  • ​io --- 处理流的核心工具​
  • #android不同版本废弃api,新api。
  • #HarmonyOS:Web组件的使用
  • #pragma once与条件编译
  • #我与Java虚拟机的故事#连载03:面试过的百度,滴滴,快手都问了这些问题
  • (4)logging(日志模块)
  • (Oracle)SQL优化基础(三):看懂执行计划顺序
  • (TipsTricks)用客户端模板精简JavaScript代码
  • (附源码)spring boot北京冬奥会志愿者报名系统 毕业设计 150947
  • (四)事件系统
  • .mysql secret在哪_MySQL如何使用索引
  • .Net MVC4 上传大文件,并保存表单
  • .NET 材料检测系统崩溃分析
  • .sh
  • /etc/X11/xorg.conf 文件被误改后进不了图形化界面
  • @Documented注解的作用
  • [ C++ ] STL priority_queue(优先级队列)使用及其底层模拟实现,容器适配器,deque(双端队列)原理了解
  • [ JavaScript ] JSON方法
  • [ Linux ] git工具的基本使用(仓库的构建,提交)
  • [ 云计算 | Azure 实践 ] 在 Azure 门户中创建 VM 虚拟机并进行验证
  • [Angular] 笔记 16:模板驱动表单 - 选择框与选项
  • [Angular] 笔记 18:Angular Router
  • [C/C++] C/C++中数字与字符串之间的转换
  • [CSS]盒子模型
  • [GPT]Andrej Karpathy微软Build大会GPT演讲(上)--GPT如何训练
  • [HDU] 1054 Strategic Game 入门树形DP