Tarjan算法求解无向连通图的割点、割边、点双连通分量和边双连通分量的模板
历时好几天,终于完工了!
支持无向图四种功能:
1.割点的求解
2.割边的求解
3.点双连通分量的求解
4.边双连通分量的求解
全部支持重边!!!!全部支持重边!!!!全部支持重边!!!!
测试数据:
10 11
1 5
3 5
4 5
2 4
2 3
4 6
6 8
6 7
7 8
8 10
8 9
/*
By:ZUFE_ZZT
该模板经过多次修改与研究,修正了很多错误,增加了很多功能。
无向图,完全支持重边!!完全支持重边!!
【功能如下】
1.求割点的编号,以及去掉割点有多少连通分量
2.求点双连通分量
3.求割边的编号
4.求边双连通分量
*/ #include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std; const int maxn=+; //结点数量
const int Maxn=*+; //边的数量
int low[maxn];
int dfn[maxn];
int U[maxn],V[maxn];//存初始边
int flag[maxn];//判断第i条边是不是割边
int iscut[maxn];//判断i结点是不是割点,去掉之后有几个连通分量
struct Edge
{
int from,to,id,ans;//ans为1,表示这条边是割边
} edge[Maxn];
vector<int>G[maxn];//邻接表
int N,M;//N个结点,M条边
int tmpdfn;//时间戳
int tot;
int son;
int Start,End; //以下是输出点双连通分量用的
int top;
struct Printf_Egde
{
int u,v,id;
void output()
{printf("(%d,%d) ",u,v);}
};
Printf_Egde Stack[Maxn];
int Flag[Maxn]; int TxT[maxn];//求边双连通分量用的 void init()
{
for(int i=; i<maxn; i++) G[i].clear();
memset(low,,sizeof(low));
memset(dfn,,sizeof(dfn));
memset(iscut,,sizeof(iscut));
memset(Flag,,sizeof(Flag));
memset(flag,,sizeof(flag));
memset(TxT,,sizeof(TxT));
low[]=dfn[]=;
tmpdfn=;
tot=;
son=;
top=-;
} void AddEdge(int u,int v)
{
edge[tot].from=u;
edge[tot].to=v;
edge[tot].id=tot;
edge[tot].ans=;
G[u].push_back(tot);
tot++; edge[tot].from=v;
edge[tot].to=u;
edge[tot].id=tot;
edge[tot].ans=;
G[v].push_back(tot);
tot++;
} int Tarjan(int u,int id)
{
tmpdfn++;
int lowu=dfn[u]=tmpdfn;
for(int i=; i<G[u].size(); i++)
{
int B=G[u][i]; Printf_Egde t;
if(!Flag[edge[B].id/])//没有入过栈
{
Flag[edge[B].id/]=;
t.u=u;
t.v=edge[B].to;
t.id=edge[B].id/;
Stack[++top]=t;
}
if(!dfn[edge[B].to])
{
int lowv=Tarjan(edge[B].to,edge[B].id);
lowu=min(lowu,lowv);
if(lowv>=dfn[u])
{
if(u!=) iscut[u]++;
if(u==) son++; //输出点双连通分量
printf("点双连通分量:");
while()
{
if(top==-) break;
Printf_Egde t1;
t1=Stack[top];
t1.output();
top--;
if(t1.id==t.id) break;
}
printf("\n"); //判断是不是割边
if(lowv>dfn[u])
edge[B].ans=;
}
}
else if(dfn[edge[B].to])
{
if(edge[B].id/==id/) continue;
lowu=min(lowu,dfn[edge[B].to]);
}
} low[u]=lowu;
return lowu;
} void Display_Cutting_edge()
{
for(int i=; i<*M; i++)
if(edge[i].ans)
printf("第%d条边是割边:(%d,%d)\n",edge[i].id/,edge[i].from,edge[i].to); } void Display_Cutting_point()
{
if(son>) iscut[]=son-;
for(int i=Start;i<=End;i++)
if(iscut[i])
printf("编号为%d的结点是割点,删除后有%d个连通分量\n",i,iscut[i]+);
} void Dfs(int x,int y)
{
int XZ=;
for(int i=;i<G[x].size();i++)
{
int B=G[x][i];
if(!flag[edge[B].id/])
{
XZ=;
flag[edge[B].id/]=;
TxT[edge[B].to]=;
printf("(%d,%d) ",edge[B].from,edge[B].to);
Dfs(edge[B].to,y+);
}
}
if(!XZ&&!y) printf("(%d) ",x);
} void Slove()
{
//把桥都标为1
for(int i=; i<*M; i++)
if(edge[i].ans)
flag[edge[i].id/]=; for(int i=Start;i<=End;i++)
{
if(!TxT[i])
{
TxT[i]=;
printf("边双连通分量:");
Dfs(i,);
printf("\n");
}
}
} int main()
{
scanf("%d%d",&N,&M);
init();
for(int i=; i<M; i++)
{
scanf("%d%d",&U[i],&V[i]);
AddEdge(U[i],V[i]);
} //设置结点编号的起点和终点
Start=;
End=N; Tarjan(,-); //割点的输出
Display_Cutting_point(); //割边的输出
Display_Cutting_edge(); //点双连通分量在Tarjan过程中已经输出了 //求边双连通分量,并输出
Slove(); return ;
}
Tarjan算法求解无向连通图的割点、割边、点双连通分量和边双连通分量的模板的更多相关文章
- TarJan 算法求解有向连通图强连通分量
[有向图强连通分量] 在有向图G中,如果两个 顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的 ...
- Tarjan算法:求解无向连通图图的割点(关节点)与桥(割边)
1. 割点与连通度 在无向连通图中,删除一个顶点v及其相连的边后,原图从一个连通分量变成了两个或多个连通分量,则称顶点v为割点,同时也称关节点(Articulation Point).一个没有关节点的 ...
- 无向连通图求割点(tarjan算法去掉改割点剩下的联通分量数目)
poj2117 Electricity Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 3603 Accepted: 12 ...
- tarjan算法--求解无向图的割点和桥
1.桥:是存在于无向图中的这样的一条边,如果去掉这一条边,那么整张无向图会分为两部分,这样的一条边称为桥 也就是说 无向连通图中,如果删除某边后,图变成不连通,则称该边为桥 2.割点:无向连通图中,如 ...
- [Tarjan系列] Tarjan算法求无向图的桥和割点
RobertTarjan真的是一个传说级的大人物. 他发明的LCT,SplayTree这些数据结构真的给我带来了诸多便利,各种动态图论题都可以用LCT解决. 而且,Tarjan并不只发明了LCT,他对 ...
- Tarjan算法求解桥和边双连通分量(附POJ 3352 Road Construction解题报告)
http://blog.csdn.net/geniusluzh/article/details/6619575 在说Tarjan算法解决桥和边双连通分量问题之前我们先来回顾一下Tarjan算法是如何 ...
- 有向图强连通分支的Tarjan算法讲解 + HDU 1269 连通图 Tarjan 结题报告
题目很简单就拿着这道题简单说说 有向图强连通分支的Tarjan算法 有向图强连通分支的Tarjan算法伪代码如下:void Tarjan(u) {dfn[u]=low[u]=++index//进行DF ...
- 20行代码实现,使用Tarjan算法求解强连通分量
今天是算法数据结构专题的第36篇文章,我们一起来继续聊聊强连通分量分解的算法. 在上一篇文章当中我们分享了强连通分量分解的一个经典算法Kosaraju算法,它的核心原理是通过将图翻转,以及两次递归来实 ...
- POJ1523:SPF(无向连通图求割点)
题目:http://poj.org/problem?id=1523 题目解析: 注意题目输入输入,防止PE,题目就是求割点,并问割点将这个连通图分成了几个子图,算是模版题吧. #include < ...
随机推荐
- 关于去除input type='file'改变组件的默认样式换成自己需要的样式的解决方案
在工作中时常会遇到如需要上传功能的按钮,而不像需要系统默认的样式时候,可以采取以下的解决方案: <img onclick="getElementById('file').click() ...
- GCD系列 之(二): 多核心的性能
全局队列的并发执行 for(id obj in array) [self doSomethingIntensiveWith:obj]; 假设,每个元素要做的事情-doSomethingIntensiv ...
- (repost)在ARM Linux内核中增加一个新的系统调用
实验平台内核版本为4.0-rc1,增加一仅仅打印Hello World的syscall,最后我们在用户空间swi验证 实验平台内核版本为4.0-rc1,增加的系统调用仅仅是简单打印一个Hello Wo ...
- ubuntu14.04 下安装mysql5.6
1.sudo apt-get install mysql-server-5.6 2.测试是否安装成功 ps aux |grep mysql mysql -u root -p 3.允许远程访问设置 su ...
- Eclipse 打开当前文件所在的文件夹
两种方法: 1.安装EasyExplorer插件,有了这个插件就可以很方便地打开资源文件所在的文件夹了. EasyExplorer 从 http://sourceforge.net/projects/ ...
- css3实现进度条
HTML 结构很简单,但不是 Single Element: <div class="spinner"><i></i></div> ...
- 解题报告8VC Venture Cup 2017 - Elimination Round
题目链接:http://codeforces.com/contest/755 本蒟蒻做了半天只会做前两道题.. A. PolandBall and Hypothesis 题意:给出n,让你找出一个m, ...
- HDU猜数字
G - 猜数字 Time Limit:10000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Descri ...
- C#.NET的微信功能开发学习
对于新手的我来说,我不是申请一个微信公众号认证后进行开发,我是申请一个订阅号,然后通过自己申请的订阅号的公众平台测试号来学习. 一,申请后成功后,打开开发者工具-公众平台测试号 二,进去公众平台测试号 ...
- 为UIView添加分类直接改或获取控件的frame值
#import <UIKit/UIKit.h> @interface UIView (SJBExtends) @property (nonatomic,assign)CGFloat x; ...