点/边 双连通分量---Tarjan算法
运用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算法的更多相关文章
- UOJ#30/Codeforces 487E Tourists 点双连通分量,Tarjan,圆方树,树链剖分,线段树
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ30.html 题目传送门 - UOJ#30 题意 uoj写的很简洁.清晰,这里就不抄一遍了. 题解 首先建 ...
- HDU4612(Warm up)2013多校2-图的边双连通问题(Tarjan算法+树形DP)
/** 题目大意: 给你一个无向连通图,问加上一条边后得到的图的最少的割边数; 算法思想: 图的边双连通Tarjan算法+树形DP; 即通过Tarjan算法对边双连通缩图,构成一棵树,然后用树形DP求 ...
- 浅谈 Tarjan 算法之强连通分量(危
引子 果然老师们都只看标签拉题... 2020.8.19新初二的题集中出现了一道题目(现已除名),叫做Running In The Sky. OJ上叫绮丽的天空 发现需要处理环,然后通过一些神奇的渠道 ...
- Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载)
Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载) 转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2 ...
- 图论算法-Tarjan模板 【缩点;割顶;双连通分量】
图论算法-Tarjan模板 [缩点:割顶:双连通分量] 为小伙伴们总结的Tarjan三大算法 Tarjan缩点(求强连通分量) int n; int low[100010],dfn[100010]; ...
- Tarjan算法初探(3):求割点与桥以及双连通分量
接上一节Tarjan算法初探(2):缩点 在此首先提出几个概念: 割点集合:一个无向连通图G 若删除它的一个点集 以及点集中所有点相连的边(任意一端在点集中)后 G中有点之间不再连通则称这个点集是它的 ...
- tarjan算法与无向图的连通性(割点,桥,双连通分量,缩点)
基本概念 给定无向连通图G = (V, E)割点:对于x∈V,从图中删去节点x以及所有与x关联的边之后,G分裂为两个或两个以上不相连的子图,则称x为割点割边(桥)若对于e∈E,从图中删去边e之后,G分 ...
- Tarjan算法求解桥和边双连通分量(附POJ 3352 Road Construction解题报告)
http://blog.csdn.net/geniusluzh/article/details/6619575 在说Tarjan算法解决桥和边双连通分量问题之前我们先来回顾一下Tarjan算法是如何 ...
- [Tarjan系列] Tarjan算法求无向图的双连通分量
这篇介绍如何用Tarjan算法求Double Connected Component,即双连通分量. 双联通分量包括点双连通分量v-DCC和边连通分量e-DCC. 若一张无向连通图不存在割点,则称它为 ...
随机推荐
- 使用Sublime Text 2 编辑Markdown
http://www.ituring.com.cn/article/6815 一.安装 下载Sublime Text 2 安装 二.安装Package Control 按Ctrl + ` 打开cons ...
- iOS-远程推送
说到远程推送,应该用的也挺多的,今天就基于SEA的云推送服务,做一个推送的小demo,来了解一下iOS中的远程推送是怎么一回事儿,首先你得有苹果的开发者账号,好咸蛋也差不多了,主要内容走起. 一.准备 ...
- sql语句中获取datetime的日期部分或时间部分
sql语句中获取datetime的日期部分 sql语句中 经常操作操作datetime类型数据.今天在写一个存储过程的时候需要将 一个datetime的值的 日期部分提取出来.网上有许多这方面的介绍. ...
- Linux常用命令03
上篇我们写到,如何编辑文件,我们有时候,在编辑的时候,有可能会异常的退出,这样的话, linux会针对这个文件生成一个swp文件,当你下次进入vi模式时,就会提示你一个错误 这样,即使你按enter键 ...
- SDWebImage清除图片缓存
背景: 使用 SDWebImage 库,由于内存中一直缓存着加载的图片,而导致内存过高(我们无法手动管理内存),弹出内存警告而导致程序很卡或者直接crash掉. 我的解决方法: 在AppDelegat ...
- 移动端BUG汇总
position:fixed问题 固定定位到底部会把最后一个元素盖住 你会发现最后一个字被盖住了,并且还滚动不下去. 解决方法: 给后一个元素添加一个高度,或者给body加margin-bottom ...
- webpack学习笔记
1.安装webpack npm install webpack -g 2.进入项目目录,初始化 npm init 3.将webpack安装到项目依赖中 npm install webpack --sa ...
- Nodejs中的this
以下内容都是关于在nodejs中的this而非javascript中的this,nodejs中的this和在浏览器中javascript中的this是不一样的. 在全局中的this console.l ...
- 【WP 8.1开发】电子罗盘
罗盘,估计也不用我过多介绍,学过初中物理的都知道,不管是指南针,还是指北针,其本质就是用来辨别方向的. 操作电子罗盘伟感器也不复杂,主要就是两个角度: 1.当前方向与磁北的夹角: 2.当前方向与地北的 ...
- 深入理解PHP内核(十二)函数-函数的定义、传参及返回值
原文链接:http://www.orlion.ga/344/ 一.函数的定义 用户函数的定义从function 关键字开始,如下 function foo($var) { echo $var; ...