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<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[] 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<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]);
        }
    }
}

}

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