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
static Set
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<Integer> cutPointList = new ArrayList<>(cutPoint);
cutPointList.sort(new Comparator<Integer>() {
@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
static List<int[]> cutEdge;
static int visitCnt;
static Set
static List
@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<Integer>() {
@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]);
}
}
}
}

浙公网安备 33010602011771号