历时好几天,终于完工了!

支持无向图四种功能:
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算法求解无向连通图的割点、割边、点双连通分量和边双连通分量的模板的更多相关文章

  1. TarJan 算法求解有向连通图强连通分量

    [有向图强连通分量] 在有向图G中,如果两个 顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的 ...

  2. Tarjan算法:求解无向连通图图的割点(关节点)与桥(割边)

    1. 割点与连通度 在无向连通图中,删除一个顶点v及其相连的边后,原图从一个连通分量变成了两个或多个连通分量,则称顶点v为割点,同时也称关节点(Articulation Point).一个没有关节点的 ...

  3. 无向连通图求割点(tarjan算法去掉改割点剩下的联通分量数目)

    poj2117 Electricity Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 3603   Accepted: 12 ...

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

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

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

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

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

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

  7. 有向图强连通分支的Tarjan算法讲解 + HDU 1269 连通图 Tarjan 结题报告

    题目很简单就拿着这道题简单说说 有向图强连通分支的Tarjan算法 有向图强连通分支的Tarjan算法伪代码如下:void Tarjan(u) {dfn[u]=low[u]=++index//进行DF ...

  8. 20行代码实现,使用Tarjan算法求解强连通分量

    今天是算法数据结构专题的第36篇文章,我们一起来继续聊聊强连通分量分解的算法. 在上一篇文章当中我们分享了强连通分量分解的一个经典算法Kosaraju算法,它的核心原理是通过将图翻转,以及两次递归来实 ...

  9. POJ1523:SPF(无向连通图求割点)

    题目:http://poj.org/problem?id=1523 题目解析: 注意题目输入输入,防止PE,题目就是求割点,并问割点将这个连通图分成了几个子图,算是模版题吧. #include < ...

随机推荐

  1. Python--变量作用域

    变量作用域: 一般在函数体外定义的变量成为全局变量,在函数内部定义的变量称为局部变量. 全局变量所有作用域都可读,局部变量只能在本函数可读 函数在读取变量时,优先读取函数本身自有的局部变量,再去读全局 ...

  2. MYSQL 命令行导入导出数据库文件

    MYSQL命令行导入数据库 1.首先通过命令行进入到mysql安装目录的bin目录下,比如我输入的命令为: cd E:\MySQL\MySQL Server 5.5\bin,输入如下命令: mysql ...

  3. 代码块(Block)回调一般阐述

    本章教程主要对代码块回调模式进行讲解,已经分析其他回调的各种优缺点和适合的使用场景. 代码块机制 Block变量类型 Block代码封装及调用 Block变量对普通变量作用域的影响 Block回调接口 ...

  4. mysql B+树 Cardinality MRR

    B+树索引并不能找到一个给定键值的具体行,而是被查找数据行所在的页.然后数据库通过把页读入到内存,再在内存中进行查找,最后得到想要查找的数据. Show index from table. Cardi ...

  5. Paxos算法简单介绍

    一种基于消息传递且具有高度容错特性的一致性算法.解决在存在宕机或者网络异常的集群中对某个数据的值达成一致性,并且保证无论在发生以上任何异常都不会破坏整个系统的一致性,具有容错性. Paxos算法实现的 ...

  6. Ubuntu下 hadoop2.5.1 (伪分布模式) 配置工作

    一:安装JDK hadoop 是以java语言写的,因此需要在本地计算机上预先安装JDK,安装JDK的方法这里不再详述. 二:创建hadoop用户 为hadoop创建一个专门的用户,将所有的hadoo ...

  7. JS复习:第六章

    创建对象 一.工厂模式 function createPerson(name,age,job){ var o = new Object(); o.name = name; o.age = age; o ...

  8. Spring的Bean之Bean的基本概念[转]

    从前面我们知道Spring其实就是一个大型的工厂,而Spring容器中的Bean就是该工厂的产品.对于Spring容器能够生产那些产品,则取决于配置文件中配置. 对于我们而言,我们使用Spring框架 ...

  9. JMS理解2

    使用JMS 的应用程序被称为JMS 客户端,处理消息路由与传递的消息系统被称为JMS Provider,而JMS 应用则是由多个JMS 客户端和一个JMS Provider 构成的业务系统.发送消息的 ...

  10. WCF、Web API、WCF REST、Web Service的区别

    Difference between WCF and Web API and WCF REST and Web Service   The .Net framework has a number of ...