运用Tarjan算法,求解图的点/边双连通分量。

1、点双连通分量【块】

割点可以存在多个块中,每个块包含当前节点u,分量以边的形式输出比较有意义。

 typedef struct{  //栈结点结构  保存边
int front;
int rear;
}BNode;
BNode block_edge[MAXL];
int top; //栈指针,指向下一个空位
int num_block; //块计数
int b1,b2; //存储块中的边 辅助信息[全局变量]
void add(int *top,int front,int rear) //边入栈
{
if(*top < MAXL)
{
block_edge[*top].front=front;
block_edge[*top].rear=rear;
(*top)++;
}
}
void del(int *top) //边出栈
{
if(*top > )
{
(*top)--;
b1=block_edge[*top].front;
b2=block_edge[*top].rear;
}
} void init_dfnlow(void) //初始化
{
depth=;
root=; //【**可自定义**】若不输出割点,可以不用
num_block=;
for(int i=;i<ALG->n;i++)
{
vis[i]=;
dfn[i]=low[i]=-;
} top=;
b1=b2=-;
for(int j=;j<ALG->e;j++)
{
block_edge[j].front=;
block_edge[j].rear =;
}
} void cutblock_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]) //非树边&&回退边
{ // 新边压栈,v!=w是防止重复计算无向图中同一条树边
add(&top,u,son); //dfn[w]<dfn[u] 是防止重复计算回退边
if(!vis[son])
{
cutblock_Tarjan(son,u);
low[u]=MIN(low[u],low[son]);
if(low[son] >= dfn[u]) //u是割点,输出连通分支,包括(u,son)
{
num_block++;
do{
del(&top);
printf("<%c,%c> ",ALG->vlist[b1].vertex,ALG->vlist[b2].vertex);
}while(!(u==b1 && son==b2));
printf("\n"); /* del(&top); //两种不同的输出形式
while(!((u==b1) && (son==b2)))
{
printf("<%c,%c>,",ALG->vlist[b1].vertex,ALG->vlist[b2].vertex);
del(&top);
}
printf("<%c,%c>\n",ALG->vlist[u].vertex,ALG->vlist[son].vertex); */
}
}
else if(son != parent)
{
low[u]=MIN(low[u],dfn[son]);
}
} ptr=ptr->next;
}
}

2、边双连通分量【缩点】

某一个点只能在一个“缩点”内,“缩点”时不包括当前节点u,分量以顶点的形式输出。

 int stack[MAXL];  //栈用于缓存缩点,存放编号
int top;
int bnode[MAXL]; //用于存储缩点,存放编号
int count_bnodeele; //分量元素计数
void init_Tarjan(void)
{
depth=;
num_bridge=;
for(int i=;i<ALG->n;i++)
{
dfn[i]=low[i]=-;
vis[i]=;
// bridge[i]=0;
stack[i]=-;
}
top=;
} void init_bnode(void) //缩点初始化
{
count_bnodeele=;
for(int i=;i<ALG->n;i++)
bnode[i]=-;
} void bridge_node_Tarjan(int u,int parent)
{
int son;
ENode *ptr=(ENode*)malloc(sizeof(ENode)); dfn[u]=low[u]=depth++; //访问+标记+入栈+遍历
vis[u]=;
stack[top++]=u;
ptr=ALG->vlist[u].firstedge;
while(ptr!=NULL)
{
son=ptr->key;
if(son!=parent && dfn[son]<dfn[u])
{
if(!vis[son])
{
bridge_node_Tarjan(son,u);
low[u]=MIN(low[u],low[son]);
if(low[son] > dfn[u]) //(u,son)是桥
{
num_bridge++;
init_bnode(); //缩点初始化
while(stack[--top] != son)
{
bnode[count_bnodeele++]=stack[top];
}
bnode[count_bnodeele]=stack[top]; for(int cn=;cn<=count_bnodeele;cn++) //缩点输出
printf("%c ",ALG->vlist[bnode[cn]].vertex);
printf("\n");
}
}
else if(son != parent)
{
low[u]=MIN(low[u],dfn[son]);
}
}
ptr=ptr->next;
}
}
while(top != ) //最后节点无法全部出栈,被自然分成一个连通分量【***此步必须要有***】
{
top--;
printf("%c ",ALG->vlist[stack[top]].vertex);
}
printf("\n");

点/边 双连通分量---Tarjan算法的更多相关文章

  1. UOJ#30/Codeforces 487E Tourists 点双连通分量,Tarjan,圆方树,树链剖分,线段树

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ30.html 题目传送门 - UOJ#30 题意 uoj写的很简洁.清晰,这里就不抄一遍了. 题解 首先建 ...

  2. HDU4612(Warm up)2013多校2-图的边双连通问题(Tarjan算法+树形DP)

    /** 题目大意: 给你一个无向连通图,问加上一条边后得到的图的最少的割边数; 算法思想: 图的边双连通Tarjan算法+树形DP; 即通过Tarjan算法对边双连通缩图,构成一棵树,然后用树形DP求 ...

  3. 浅谈 Tarjan 算法之强连通分量(危

    引子 果然老师们都只看标签拉题... 2020.8.19新初二的题集中出现了一道题目(现已除名),叫做Running In The Sky. OJ上叫绮丽的天空 发现需要处理环,然后通过一些神奇的渠道 ...

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

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

  5. 图论算法-Tarjan模板 【缩点;割顶;双连通分量】

    图论算法-Tarjan模板 [缩点:割顶:双连通分量] 为小伙伴们总结的Tarjan三大算法 Tarjan缩点(求强连通分量) int n; int low[100010],dfn[100010]; ...

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

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

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

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

  8. Tarjan算法求解桥和边双连通分量(附POJ 3352 Road Construction解题报告)

     http://blog.csdn.net/geniusluzh/article/details/6619575 在说Tarjan算法解决桥和边双连通分量问题之前我们先来回顾一下Tarjan算法是如何 ...

  9. [Tarjan系列] Tarjan算法求无向图的双连通分量

    这篇介绍如何用Tarjan算法求Double Connected Component,即双连通分量. 双联通分量包括点双连通分量v-DCC和边连通分量e-DCC. 若一张无向连通图不存在割点,则称它为 ...

随机推荐

  1. 我心中的核心组件(可插拔的AOP)~第二回 缓存拦截器

    回到目录 AOP面向切面的编程,也称面向方面的编程,我更青睐于前面的叫法,将一个大系统切成多个独立的部分,而这个独立的部分又可以方便的插拔在其它领域的系统之中,这种编程的方式我们叫它面向切面,而这些独 ...

  2. Bootstrap~日期控制

    回到目录 一个成熟的框架,日期控制是少不了的,在网上也有很多日期控制可以选择,而主框架用了bootstrap,日期控制也当前要用它自己的, 控件地址:http://www.bootcss.com/p/ ...

  3. 树形打印lua table表

    为方便调试lua程序,往往想以树的形式打印出一个table,以观其表内数据.以下罗列了三种种关于树形打印lua table的方法;法一 local print = print local tconca ...

  4. salesforce 零基础开发入门学习(九)Approval Process 介绍

    在阅读此篇文章前,可以先参考阅读一个前辈总结的关于Approval Process的操作.以下为参考的链接: http://www.cnblogs.com/mingmingruyuedlut/p/37 ...

  5. iOS-Objective-C内存管理

    内存管理: 栈区 [stack]:由编译器自动分配并释放,一般存放函数的参数值,局部变量等 堆区 [heap]:由程序员分配和释放,如果程序员不释放,程序结束时,可能会由操作系统回收 全局区(静态区) ...

  6. 每天一个linux命令(24):Linux文件类型与扩展名

    Linux文件类型和Linux文件的文件名所代表的意义是两个不同的概念.我们通过一般应用程序而创建的比如file.txt.file.tar.gz ,这些文件虽然要用不同的程序来打开,但放在Linux文 ...

  7. CCNA基础 IP地址子网划分

    计算机是一个非常神奇的物品,它的核心算法是凌驾于任何代码架构.然而互联网网络( Internat )作为整个生态的基础资源.什么?你还不会子网划分? 没关系,看到子网掩码不要怕.因为它无非就是问你 & ...

  8. SQL Server 2012 T-SQL 新特性

    序列 Sequence SQL Server 现在将序列当成一个对象来实现,创建一个序列的例子语法如下: CREATE SEQUENCE DemoSequence START WITH 1 INCRE ...

  9. 如何查看某个查询用了多少TempDB空间

        最近帮助客户调优的过程中,发现客户的TempDB存在非常大的压力,经过排查是发现某些语句对TempDB的巨量使用所导致.     在SQL Server中,TempDB主要负责供下述三类情况使 ...

  10. SQL Server中一个隐性的IO性能杀手-Forwarded record

    简介     最近在一个客户那里注意到一个计数器很高(Forwarded Records/Sec),伴随着间歇性的磁盘等待队列的波动.本篇文章分享什么是forwarded record,并从原理上谈一 ...