使用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. Field 'id' doesn't have a default value

    首先原因在于没有设置主键自增长. mysql的自增长模式是IDENTITY. jpa标签: @Id @GeneratedValue(strategy=GenerationType.IDENTITY) ...

  2. PHP中Trait特性

    Trait是自 PHP 5.4.0 起添加的一个新特性,是 PHP 多重继承的一种解决方案.例如,需要同时继承两个 Abstract Class, 这将会是件很麻烦的事情,Trait 就是为了解决这个 ...

  3. javascript获取表单值的7种方式

    见代码: <!doctype html> <html lang="en"> <head> <meta charset="UTF- ...

  4. Java程序员的日常—— POI与JDBC、Mockmvc与单元测试

    周日没怎么休息好,周一一天都迷迷糊糊的,不过还算是干了不少的活. 总结一下,大致有以下几点内容: 1 使用poi以及mysql jdbc实现了一个复杂excel的导入 2 基于工程原有的代码,书写sp ...

  5. Android ListView 进阶学习

    1.使用ListView展示数据结构为二维数组的数据 当我们遇到数据结构是二维数组的需求的时候,我们会首先想到ListView,但是要想实现二维数组,会想到ListView里面嵌套ListView,但 ...

  6. 快速入门系列--GIT版本控制工具

    由于GIT刚刚开始使用不久,经常会在Merge时出现没有change-id的情况,在结合gerrit使用时,经常出现不能提交的情形,使得自己很困扰.最近有次熬夜加班,在代码完成后,由于多人在很短时间内 ...

  7. jQuery尺寸算法

    我们默认都统一是采用offsetWidth或者offsetHeight取值了,但我们知道关于这2个尺寸的算法是这样的: offsetWidth = border-left-width + paddin ...

  8. WPF自定义控件与样式(13)-自定义窗体Window & 自适应内容大小消息框MessageBox

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 自定义 ...

  9. 【博客美化】05.添加GitHub链接

    博客园美化相关文章目录: [博客美化]01.推荐和反对炫酷样式 [博客美化]02.公告栏显示个性化时间 [博客美化]03.分享按钮 [博客美化]04.自定义地址栏logo [博客美化]05.添加Git ...

  10. javascript运算符——关系运算符

    × 目录 [1]恒等 [2]相等 [3]大于[4]小于 前面的话 关系运算符用于测试两个值之间的关系,根据关系是否存在而返回true或false,关系表达式总是返回一个布尔值,通常在if.while或 ...