Tarjan 算法求无向图的割顶和桥

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;
const int N = 250;

int head[N], low[N], dfn[N], fa[N];
int n, m, now = 1, Tarjan_clock;
bool is_cut[N];
struct Node{
	int u, v, nxt;
}E[N];

inline int read()
{
	int x = 0; char c = getchar();
	while(c < ‘0‘ || c > ‘9‘) c = getchar();
	while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = getchar();
	return x;
}

inline void add(int u, int v)
{
	E[now].v = v;
	E[now].nxt = head[u];
	head[u] = now ++;
}

void Tarjan(int x, int fa_x)
{
	low[x] = dfn[x] = ++ Tarjan_clock;
	fa[x] = fa_x;
	for(int i = head[x]; ~ i; i = E[i].nxt)
	{
		int v = E[i].v;
		if(!dfn[v])
		{
			Tarjan(v, x);
			low[x] = min(low[x], low[v]);
		}
		else
			if(v != fa_x)
				low[x] = min(low[x], dfn[v]);
	}
}

inline void August_13th()
{
	int root_son = 0;
	Tarjan(1, 0);
	for(int i = 2; i <= n; i ++)
	{
		int fa_i = fa[i];
		if(fa_i == 1)
			root_son ++;
		else
			if(low[i] >= dfn[fa_i])
				is_cut[fa_i] = 1;
	}
	if(root_son > 1)
		is_cut[1] = 1;
	for(int i = 1; i <= n; i ++)
		if(is_cut[i])
			printf("%d\n", i);
	for(int i = 1; i <= n; i ++)
	{
		int fa_i = fa[i];
		if(fa_i > 0 && low[i] > dfn[fa_i])
			printf("%d,%d\n",fa_i,i);
	}
}

int main()
{
	n = read();
	m = read();
	for(int i = 1; i <= n; i ++)
		head[i] = -1;
	for(int i = 1; i <= m; i ++)
	{
		int u = read();
		int v = read();
		add(u, v);
		add(v, u);
	}
	August_13th();

	return 0;
}

  

时间: 2024-07-29 02:57:09

Tarjan 算法求无向图的割顶和桥的相关文章

无向图的割顶和桥,无向图的双连通分量入门详解及模板 -----「转载」

https://blog.csdn.net/stillxjy/article/details/70176689 割顶和桥:对于无向图G,如果删除某个节点u后,连通分量数目增加,则称u为图的割顶:如果删除某条边后,连通分量数目增加,则称该边为图的桥.对于连通图删除割顶或桥后都会使得图不再连通 以下我,我们利用dfs的性质来快速找出一个连通图中的所有的割顶和桥 首先我们要引入”时间戳”这个概念: 时间戳:表示在进行dfs时,每个节点被访问的先后顺序.每个节点会被标记两次,分别用pre[],和post

连通分量 无向图的割顶和桥 无向图的双连通分量 有向图的强连通分量

时间戳 dfs_clock :说白了就是记录下访问每个结点的次序.假设我们用 pre 保存,那么如果 pre[u] > pre[v], 那么就可以知道先访问的 v ,后访问的 u . 现在给定一条边, (u, v), 且 u 的祖先为 fa, 如果有 pre[v] < pre[u] && v != fa, 那么 (u, v) 为一条反向边. 1 求连通分量: 相互可达的节点称为一个连通分量: #include <iostream> #include <cstd

无向图的割顶和桥

割顶: 关键点,删掉这个点后,图的连通分量 + 1: 桥: 在割顶的基础上,发现删除 (u,v) 这条边,图就变成非连通的了. 如何找出所有割顶和桥: 时间戳: 在无向图的基础上,DFS建树的过程中,各点进栈和出栈的时间 dfs_clock,进栈的时间 pre[],出栈的时间 post[] 在DFS程序中的体现就是: void previst(int u) { pre[u]= ++dfs_clock; } void postvist(int u) { post[u] = ++dfs_clock;

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

一.基本概念 1.桥:是存在于无向图中的这样的一条边,如果去掉这一条边,那么整张无向图会分为两部分,这样的一条边称为桥无向连通图中,如果删除某边后,图变成不连通,则称该边为桥. 2.割点:无向连通图中,如果删除某点后,图变成不连通,则称该点为割点. 二:tarjan算法在求桥和割点中的应用 1.割点:1)当前节点为树根的时候,条件是“要有多余一棵子树”(如果这有一颗子树,去掉这个点也没有影响,如果有两颗子树,去掉这点,两颗子树就不连通了.) 2)当前节点U不是树根的时候,条件是“low[v]>=

无向图的割顶和桥的性质 以及双连通分量的求解算法

割顶:对于无向图G,如果删除某个点u后,连通分量的数目增加, 称u为图的割顶.对于连通图,割顶就是删除之后使图不再连通的点. 割顶的求解依如下定理: 在无向连通图G的DFS树中,非根结点u是G的割顶当且仅当u存在一个子节点v,使得v及其所有后代都没有反向边连回u的祖先(连回u)不算. 算法实现: 采用时间戳,在dfs遍历的过程中给每个节点u均标记以前序时间戳pre[u],设low[u]为u及其后代所能连回的最早的祖先的pre值,则定理中的条件就可以简写成结点u存在一个子结点v,使得 low[v]

Light OJ - 1026 - Critical Links(图论-Tarjan算法求无向图的桥数) - 带详细注释

 原题链接   无向连通图中,如果删除某边后,图变成不连通,则称该边为桥. 也可以先用Tajan()进行dfs算出所有点 的low和dfn值,并记录dfs过程中每个 点的父节点:然后再把所有点遍历一遍, 看其low和dfn,满足dfn[ fa ]<low[ i ](0<i<=n, i 的 father为fa) -- 则桥为fa-i. 找桥的时候,要注意看有没有重边:有重边,则不是桥. 另外,本题的题意及测试样例中没有重边,所以不用考虑重边. 带详细注释的题解: #include<s

利用Stoer-Wagner算法求无向图最小割

直接给出算法描述和过程实现: 算法步骤: 1. 设最小割cut=INF, 任选一个点s到集合A中, 定义W(A, p)为A中的所有点到A外一点p的权总和. 2. 对刚才选定的s, 更新W(A,p)(该值递增). 3. 选出A外一点p, 且W(A,p)最大的作为新的s, 若A!=G(V), 则继续2. 4. 把最后进入A的两点记为s和t, 用W(A,t)更新cut. 5. 新建顶点u, 边权w(u, v)=w(s, v)+w(t, v), 删除顶点s和t, 以及与它们相连的边. 6. 若|V|!=

SPF Tarjan算法求无向图割点(关节点)入门题

SPF 题目抽象,给出一个连通图的一些边,求关节点.以及每个关节点分出的连通分量的个数 邻接矩阵只要16ms,而邻接表却要32ms,  花费了大量的时间在加边上. //   time  16ms 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <string&

无向图的割顶和桥(tarjan模板)

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; #define maxn 7500 #define inf 0x3f3f3f3f int first[maxn],to[maxn],nxt[maxn],e; int pre[maxn],low[maxn]; int clock; int iscut[maxn]; void