使用Tarjan算法求解图的割点和桥。

1、割点

主要的算法结构就是DFS,一个点是割点,当且仅当以下两种情况:
        (1)该节点是根节点,且有两棵以上的子树;
        (2)该节点的任一子节点,没有到该节点祖先的反向边(就是说如果没有这个割点,那么这个子节点和那个祖先之间不连通);

 void cutpoint_Tarjan(int u,int parent)
{
int son; //节点m的儿子节点
ENode *ptr=(ENode *)malloc(sizeof(ENode)); dfn[u]=low[u]=depth++; //访问+标记+遍历
vis[u]=;
ptr=ALG->vlist[u].firstedge;
while(ptr!=NULL)
{
son=ptr->key;
if(!vis[son])
{
DFS(son,u);
low[u]=MIN(low[u],low[son]); if(u==root) //不同之处//根节点[要定义初始访问节点,因为要考虑割点的2个判断条件]
cut[u]++;
else if(u!=root && dfn[u] <= low[son])
cut[u]++; //m是割点
}
else if(son != parent) //有后向边
{
low[u]=MIN(low[u],dfn[son]);
}
ptr=ptr->next;
}
}

2、桥

Tarjan算法求割边(桥):
【1】使用(son!=parent && dfn[son]<dfn[u]);

 void init_Tarjan(void)
{
depth=;
for(int i=;i<ALG->n;i++)
{
dfn[i]=low[i]=-;
vis[i]=;
} num_bridge=;
for(int j=;j<ALG->e;j++)
{
bridge_Node[j].front=;
bridge_Node[j].rear =;
}
} void Add_to_BNode(int front,int rear) //从坐标1开始存储
{
bridge_Node[num_bridge].front=front;
bridge_Node[num_bridge].rear =rear;
} void bridgenode_Tarjan(int u,int parent)
{
int son;
ENode *ptr=(ENode*)malloc(sizeof(ENode)); dfn[u]=low[u]=depth++; //访问+标记+遍历
vis[u]=;
ptr=ALG->vlist[u].firstedge;
while(ptr!=NULL)
{
son=ptr->key;
if(son!=parent && dfn[son]<dfn[u]) //避免走重边,效果和id一样
{
if(!vis[son])
{
bridge_node_Tarjan(son,u);
low[u]=MIN(low[u],low[son]);
if(low[son] > dfn[u]) //(u,son)是桥
{
num_bridge++;
Add_to_BNode(u,son); //存储桥
}
}
else if(son != parent)
{
low[u]=MIN(low[u],dfn[son]);
}
}
ptr=ptr->next;
}
}

【2】为每一条边标号 id记录每条边(一条无向边拆成的两条有向边id相同),每个点的父亲到它的边的标号;

 //结点定义  /*****注意边表节点定义有所变化****/
typedef struct edge_node{
int key; //儿子节点[边的终点]
int id; //边的编号
struct edge_node *next;
}ENode;
void init_Tarjan(void) //Tarjan算法初始化
{
depth=;
for(int i=;i<ALG->n;i++)
{
vis[i]=;
dfn[i]=low[i]=-;
}
count_bridge=;
for(int j=;j<=ALG->e;j++) //取值于1-e
bridge[j]=;
}
void bridge_Tarjan(int u,int id) //id是u的父亲边的编号
{
int son; //u的儿子节点
ENode *ptr=(ENode *)malloc(sizeof(ENode)); dfn[u]=low[u]=depth++; //访问+标记+遍历
vis[u]=;
ptr=ALG->vlist[u].firstedge;
while(ptr!=NULL)
{
if(ptr->id != id) //避免走重边,相当于cutpoint_Tarjan中的(son != parent)
{
son=ptr->key;
if(!vis[son])
{
bridge_Tarjan(son,ptr->id);
low[u]=MIN(low[u],low[son]);
if(dfn[u] < low[son]) //注意不取等号,当DFN[u]==LOW[v]时,当u->v dfs递归,存在一条v->u的回边,使得LOW[v]=DFN[u];故不为桥
{
bridge[ptr->id]=; //第id边是桥
printf("(%c,%c) ",ALG->vlist[u].vertex,ALG->vlist[son].vertex); //用于输出割边
}
}
else
{
low[u]=MIN(low[u],dfn[son]);
}
}
ptr=ptr->next;
}
}

割点和桥---Tarjan算法的更多相关文章

  1. 无向图的割点和桥 tarjan 模板

    #include <bits/stdc++.h> using namespace std; const int MAXN = 20005; const int MAXM = 100005; ...

  2. tarjan算法--求无向图的割点和桥

    一.基本概念 1.桥:是存在于无向图中的这样的一条边,如果去掉这一条边,那么整张无向图会分为两部分,这样的一条边称为桥无向连通图中,如果删除某边后,图变成不连通,则称该边为桥. 2.割点:无向连通图中 ...

  3. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载)

    Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载) 转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2 ...

  4. Tarjan算法:求解图的割点与桥(割边)

    简介: 割边和割点的定义仅限于无向图中.我们可以通过定义以蛮力方式求解出无向图的所有割点和割边,但这样的求解方式效率低.Tarjan提出了一种快速求解的方式,通过一次DFS就求解出图中所有的割点和割边 ...

  5. tarjan算法(强连通分量 + 强连通分量缩点 + 桥(割边) + 割点 + LCA)

    这篇文章是从网络上总结各方经验 以及 自己找的一些例题的算法模板,主要是用于自己的日后的模板总结以后防失忆常看看的, 写的也是自己能看懂即可. tarjan算法的功能很强大, 可以用来求解强连通分量, ...

  6. tarjan算法--求解无向图的割点和桥

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

  7. Tarjan算法初探(3):求割点与桥以及双连通分量

    接上一节Tarjan算法初探(2):缩点 在此首先提出几个概念: 割点集合:一个无向连通图G 若删除它的一个点集 以及点集中所有点相连的边(任意一端在点集中)后 G中有点之间不再连通则称这个点集是它的 ...

  8. tarjan算法与无向图的连通性(割点,桥,双连通分量,缩点)

    基本概念 给定无向连通图G = (V, E)割点:对于x∈V,从图中删去节点x以及所有与x关联的边之后,G分裂为两个或两个以上不相连的子图,则称x为割点割边(桥)若对于e∈E,从图中删去边e之后,G分 ...

  9. [Tarjan系列] Tarjan算法求无向图的桥和割点

    RobertTarjan真的是一个传说级的大人物. 他发明的LCT,SplayTree这些数据结构真的给我带来了诸多便利,各种动态图论题都可以用LCT解决. 而且,Tarjan并不只发明了LCT,他对 ...

随机推荐

  1. 手把手教你用python打造网易公开课视频下载软件5-python生成exe程序

    python程序生成exe文件,使用的是py2exe扩展包,下面写下具体的步骤: 第一步:新建conver2exe.py,内容如下: #coding:utf-8 from distutils.core ...

  2. statcounter统计的浏览器市场占有率

      Source: StatCounter Global Stats - Browser Market Share

  3. MySQL记录

    1.unixtime和可读时间的转换 unixtime是距"1970-01-01 08:00:00"的时间秒数 unixtime -> readable select fro ...

  4. mongodb java spring data

    关于如何集成spring-data-mongodb到项目中,已经有很多人介绍了,这里只给出几个链接. GETTING STARTED Accessing Data with MongoDB: http ...

  5. Oracle动态执行语句

      一.为什么要使用动态执行语句? 由于在PL/SQL 块或者存储过程中只支持DML语句及控制流语句,并不支持DDL语句,所以Oracle动态执行语句便应允而生了.关于DDL与DML的区别,请参见:D ...

  6. Atitit qzone qq空间博客自动点赞与评论工具的设计与实现

    Atitit qzone qq空间博客自动点赞与评论工具的设计与实现 Qzone发送评论的原理 首先,有个a标签, <a class="c_tx3" href="j ...

  7. webpack配置详解

    webpack配置详解 先点个赞吧,再挨个点下面的连接,觉得不值这个赞的回来骂我啊. Webpack傻瓜式指南(一) Webpack傻瓜指南(二)开发和部署技巧 Webpack傻瓜式指南 原生的官网详 ...

  8. 每天学点前端——基础篇1:css盒子模型,绝对定位和相对定位

    什么是css盒子模型(Box Model)? W3C中解释为:规定了元素框处理元素内容.内边距.边框和外边距的方式: MDN:文档中的每个元素被描绘为矩形盒子.渲染引擎的目的就是判定大小,属性--比如 ...

  9. css绘制三角形原理

    1.新建一个元素,将它的宽高都设置为0:然后通过设置border属性来实现三角形效果,下面是css绘制三角形的原理: <!DOCTYPE html> <html> <he ...

  10. Control Flow 如何处理 Error

    在Package的执行过程中,如果在Data Flow中出现Error,那么Data Flow component能够将错误行输出,只需要在组件的ErrorOutput中进行简单地配置,参考<D ...