Tarjan 模板 计算割点 Java实现

题目:[模板] 割点

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;

public class Main implements Runnable{
static int[] dfn,low,parent;
static boolean[] mark;
static int visitCnt;
static LinkedList[] adj;
static Set cutPoint;

static class Edge{
int from,to;

public Edge(int from, int to) {
this.from = from;
this.to = to;
}
}

public static void main(String[] args) throws Exception{
new Thread(null,new Main(),"",1<<29).start();
}

@Override
public void run() {
try{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());

int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());

dfn = new int[n+1];
low = new int[n+1];
parent = new int[n+1];

mark = new boolean[n+1];

cutPoint = new HashSet<>();

adj = new LinkedList[n+1];
for(int i = 0;i<adj.length;i++){
adj[i] = new LinkedList<>();
}

int from,to;
for(int i = 0;i<m;i++){
st = new StringTokenizer(br.readLine());
from = Integer.parseInt(st.nextToken());
to = Integer.parseInt(st.nextToken());
adj[from].add(new Edge(from,to));
adj[to].add(new Edge(to,from));
}

for(int i = 1;i<=n;i++){
if(!mark[i]){
dfs(i);
}
}

int rsCnt = cutPoint.size();
List cutPointList = new ArrayList<>(cutPoint);
cutPointList.sort(new Comparator() {
@Override
public int compare(Integer integer, Integer t1) {
return integer-t1;
}
});

System.out.println(rsCnt);
for(int point:cutPointList){
System.out.print(point+" ");
}

}catch (Exception e){
e.printStackTrace();
}
}

private static void dfs(int start){
int childTreeCnt = 0;

dfn[start] = low[start] = visitCnt;
parent[start] = -1;
mark[start] = true;

for(Edge e:adj[start]){
int to = e.to;
if(!mark[to]){
mark[to] = true;
parent[to] = start;
dfs0(to);
childTreeCnt++;
}
}

if(childTreeCnt>=2){
cutPoint.add(start);
}
}

private static void dfs0(int from){
dfn[from] = low[from] = ++visitCnt;
for(Edge e:adj[from]){
int to = e.to;
if(!mark[to]){
mark[to] = true;
parent[to] = from;
dfs0(to);

low[from] = Math.min(low[from],low[to]);
if(low[to]>=dfn[from]){
cutPoint.add(from);
}
}
else{
low[from] = Math.min(low[from],dfn[to]);
}
}
}
}

这个是包含割边计算的代码:

package judge.P3388;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main implements Runnable{
static boolean[] mark, isCutPoint;
static int[] dfn, low, parent;
static LinkedList[] adj;
static List<int[]> cutEdge;
static int visitCnt;
static Set cutPointSet;
static List cutPointList;

@Override
public void run() {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = null;
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}

int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
dfn = new int[n + 1];
low = new int[n + 1];
parent = new int[n + 1];
mark = new boolean[n + 1];
isCutPoint = new boolean[n + 1];
visitCnt = 0;
adj = new LinkedList[n + 1];
cutEdge = new ArrayList<>();
cutPointSet = new HashSet<>();
cutPointList = new ArrayList<>();

for (int i = 0; i < adj.length; i++) {
adj[i] = new LinkedList<>();
}

int from, to;
for (int i = 0; i < m; i++) {
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
from = Integer.parseInt(st.nextToken());
to = Integer.parseInt(st.nextToken());
adj[from].add(new Edge(from, to));
adj[to].add(new Edge(to, from));
}
for(int i = 1;i<=n;i++){
if(!mark[i]){
dfs(i);
}
}
System.out.println(cutPointSet.size());
cutPointList = new ArrayList<>(cutPointSet);
cutPointList.sort(new Comparator() {
@Override
public int compare(Integer o1, Integer o2) {
return o1-o2;
}
});
for(int p:cutPointList){
System.out.print(p+" ");
}
}

static class Edge {
int from, to;

public Edge(int from, int to) {
this.from = from;
this.to = to;
}
}

public static void main(String[] args) throws Exception {
new Thread(null, new Main(), "", 1 << 29).start();
}

private static void dfs(int from) {
int childTreeCnt = 0;
dfn[from] = low[from] = visitCnt;
parent[from] = -1;
mark[from] = true;
for (Edge e : adj[from]) {
int to = e.to;
if (!mark[to]) {
mark[to] = true;
parent[to] = from;
dfs0(to);

if (low[to] > dfn[from]) {
cutEdge.add(new int[]{from, to});
}
childTreeCnt++;
}
}
if (childTreeCnt >= 2) {
isCutPoint[from] = true;
cutPointSet.add(from);
}
}

private static void dfs0(int from) {
dfn[from] = low[from] = ++visitCnt;
for (Edge e : adj[from]) {
int to = e.to;
if (!mark[to]) {
mark[to] = true;
parent[to] = from;

dfs0(to);
low[from] = Math.min(low[from], low[to]);
if (low[to] >= dfn[from]) {
isCutPoint[from] = true;
cutPointSet.add(from);
if (low[to] > dfn[from]) {
cutEdge.add(new int[]{Math.min(from, to), Math.max(from, to)});
}
}
} else if (parent[from] != to && dfn[to] < dfn[from]) {
low[from] = Math.min(low[from], dfn[to]);
}
}
}
}

posted @ 2021-04-30 17:21  Monstro  阅读(133)  评论(0)    收藏  举报