图论---割点与割边

割点和割边

割点与割边是在无向图中讨论的问题。
割点,即删除某个顶点,原图不再连通,这样的顶点称为割点。有时候也叫 “割顶”。割边是与割点性质类似的边(有时候叫做 “桥”)。求割点和割边同样利用Tarjan算法的 dfn[ ]数组和 low[ ]数组。
注意由于不同于求强连通分量,割点和割边是无向图上的问题,因此 low[ ] 数组的含义有细微变化,见后文。

Tarjan算法求割点

在Tarjan算法求强连通分量的过程中,讨论了 dfn[i] = low[i] 的情况,这意味着结点 i 不能通过其子孙结点回到更早的时间戳了,也就是说顶点 i 是一个强连通分量的起点。
同样也可以用 dfn[i] 和 low[i] 的关系,确定顶点 i 是否为割点。
分以下两种情况:

  1. 顶点 u 是搜索树的根节点。
    此时,如果在搜索树中,顶点 u 有两个以上的孩子。则顶点 u 一定是割点,因为此时如果去掉顶点 u ,那么其不同子树之间的结点必定不可到达。
  2. 顶点 u 不是搜索树的根节点。
    此时,如果对于边 (u,v)如果 low[v] >= dfn[u],则说明结点u是一个割点。

low[v] >= dfn[u],意味着结点v不能通过除边(u,v)以外的边回到其搜索树中的祖先结点,那么当去掉结点u时,结点v便会和其祖先结点分开。此时结点u就是一个割点。

代码

int Tarjan(int u, int fa)   //当前搜索结点和其父节点 返回当前搜索节点的low值 
{
	dfn[u] = ++deep;
	int lowu = dfn[u], child = 0;
	int sz = G[u].size();
	for(int i=0;i=dfn[u])
			{
				iscut[u] = 1;
			}
		}
		else
		{
			if(v!=fa&&dfn[v]

关于到底是 low[u] = min(low[u],dfn[v]) 还是 low[u] = min(low[u],low[v]) 的问题,求强连通分量时,两种写法都可以,但是求割点时只有 low[u] = min(low[u],dfn[v]) 是正确的,具体原因我目前也没明白。所以最好统一一下,都写成 low[u] = min(low[u],dfn[v])

Tarjan算法求割边

基本思路与求割点一致,当一条边(u,v),有 low[v] > dfn[u],则如果不经过边(u,v),顶点v不能访问到更早的时间戳,边(u,v)是一条割边。

int Tarjan(int u, int fa)
{
	dfn[u] = ++deep;
	int lowu = dfn[u], child = 0;
	int sz = G[u].size();
	for(int i=0;idfn[u])
			{
				int from = u, to = v;
				if(from>to)     //做了一个从小序号开始大序号结束的处理
				{
					int t = from;
					from = to;
					to = t;
				}
				bridge[++pb].from = from;
				bridge[pb].to = to;
			}
		}
		else
		{
			if(v!=fa&&dfn[v]

例题

求割点模板:洛谷P3388 【模板】割点(割顶).
求割边模板:洛谷P1656 炸铁路.

你可能感兴趣的:(图论)