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

支持无向图四种功能:
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. studio_svn

    最新升级IDEA12到13版本,升级后发现IDEA中SVN无法正常使用,但文件夹下能够正常使用. 并且报错:svn: E204899: Cannot run program "svn&quo ...

  2. uitabbarController tababr 上方横线隐藏

    在自定义的tabbarController里加上这一句就ok [[UITabBar appearance] setShadowImage:[UIImage new]]; [[UITabBar appe ...

  3. Debian7安装php5.5/5.6

    ### 1 添加源 echo "deb http://packages.dotdeb.org wheezy-php56 all" >> /etc/apt/sources ...

  4. Mybatis的传参

    最近重新温习了遍Mybatis ,觉得还是汇总一下比较好,方便自己以后的快速开发 最终要的一点事,自己写的话,记忆更加深刻: 首先自己先写了个静态块,防止代码冗余: private static Sq ...

  5. fork()子进程与waitpid()

    #!/usr/bin/perl use warnings; use strict; use POSIX ":sys_wait_h"; $SIG{CHLD} = sub{ my $p ...

  6. 使用SQL Server视图的优缺点

    SQL Server视图我们经常会用的到,下面就为您介绍使用SQL Server视图的优缺点,希望可以对您SQL Server视图有更多的了解. 在程序设计的时候必须先了解视图的优缺点,这样可以扬长避 ...

  7. jsvc 以daemon方式运行tomcat

    原理: 使用jsvc来运行服务,没有了默认8005的shutdown端口: 主进程pid为1,fork 2个进程 运行方式参考:http://commons.apache.org/proper/com ...

  8. Oracle sql 中的字符(串)替换与转换[转载]

    1.REPLACE 语法:REPLACE(char, search_string,replacement_string) 用法:将char中的字符串search_string全部转换为字符串repla ...

  9. android 操蛋的gradle

    首先看语法: -include {filename} 从给定的文件中读取配置参数 -basedirectory {directoryname} 指定基础目录为以后相对的档案名称 -injars {cl ...

  10. C#中Invoke的用法

    在用.NET Framework框架的WinForm构建GUI程序界面时,如果要在控件的事件响应函数中改变控件的状态,例如:某个按钮上的文本原先叫"打开",单击之后按钮上的文本显示 ...