图论 Tarjan算法求 割点

Tarjar算法可以解决很多连通性问题,我的上一篇文章是用Tarjan解决强联通分量问题。
在这里插入图片描述

我们用dfn[ ]数组记录一个节点的遍历编号,也就是第几次遍历到的点。low[ ]代表一个节点能到达最小的点,不经过父节点。
比如
1.第一种情况是判定普通节点是否为割点。我们从节点1做为起点开始遍历,到2这个点发现有其他路可以到1。同理3节点也有路到他的祖先。这时暂时判定3不是割点,但是2还有为遍历的点。到节点4的时候,发现low[4]>=dfn[2],且2不是起始节点,那么我们判定2是割点。
在这里插入图片描述

2.第二种情况是判定起始节点是否为割点。我们从节点4开始,会发现low[2]>=dfn[4],如果按照上面的方法,4就是割点。很显然不是,对于起始节点的判定是,只要起始节点的度为2及以上,那么起始节点就是割点。就像我们从1开始一样,1不被判定为割点。

下面是一道模板题:洛谷 【模板】割点(割顶)
详细代码附上:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.ArrayList;


public class Temp {

	static int num=0;
	static ArrayList<Integer>[] g;
	static int[] dfn,low;
	static boolean[] cut;
	public static void main(String[] args) throws IOException {
		StreamTokenizer in=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
		PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
		int N,M,u,v;
		in.nextToken();N=(int)in.nval;
		in.nextToken();M=(int)in.nval;
		g=new ArrayList[N+1];
		dfn=new int[N+1];
		low=new int[N+1];
		cut=new boolean[N+1];
		for(int i=0;i<=N;i++)
			g[i]=new ArrayList<Integer>();
		for(int i=0;i<M;i++)
		{
			in.nextToken();u=(int)in.nval;
			in.nextToken();v=(int)in.nval;
			g[u].add(v);g[v].add(u);
		}
		//上面都是初始化
		for(int i=1;i<=N;i++)
			if(dfn[i]==0)
				Tarjan(i, i);
		for(int i=1;i<=N;i++)
			if(cut[i])
			{
				pw.println(i);
				pw.flush();
			}
		pw.flush();
	}
	//模板开始
	static void Tarjan(int x,int farther)
	{
		int t;
		dfn[x]=low[x]=++num;
		for(int i=0;i<g[x].size();i++)
		{
			t=g[x].get(i);
			if(dfn[t]==0)
			{
				Tarjan(t, farther);
				low[x]=Math.min(low[x],low[t]);
				if(low[t]>=dfn[x]&&x!=farther)
					cut[x]=true;
			}
			else
				low[x]=Math.min(low[x], dfn[t]);
		}
		if(g[x].size()>=2&&x==farther)  //size<2的话代表这个节点是度为1的节点,不可能是割点
			cut[x]=true;
	}
	//模板结束
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值