中文
[BOJ 4803, Java] 树

[BOJ 4803, Java] 树

BOJ 4803,“树”题的 Java 解法

题目链接

[BOJ 4803](https://www.acmicpc.net/problem/4803

)

分类

数据结构(data_structures)、深度优先搜索(dfs)、不相交集合(disjoint_set)、图论(graphs)、图遍历(graph_traversal)、树(trees)

说明

这是一道利用树的性质来统计树的数量的问题。本题可以通过排除由连接元素构成的结构中的环来解决。

  1. 检查所有节点是否已被访问
  2. 对于未访问的节点,将其纳入树中并进行深度遍历
  3. 若形成环,则将构成该环的所有节点标记为已访问
  4. 若未形成环,则该集合为树,计数为1

通过上述逻辑进行了实现,在思考如何在深度遍历过程中进行计数处理后,最终编写了如下代码:


    public static int dfs(int nowNode, int parent, boolean[] visitLog, HashMap<Integer, ArrayList<Integer>> graph) {

        for (int nextNode : graph.get(nowNode)) {

            if (nextNode != parent && !visitLog[nextNode]) {

                visitLog[nextNode] = true;

                int result = dfs(nextNode, nowNode, visitLog, graph);
                if (result == 0) {
                    return 0;
                }

            } else if (nextNode != parent && visitLog[nextNode]) {
                return 0;
            }

        }

        return 1;

    }

该代码从起始点开始以递归形式进行访问和检查,当出现环时,默认遍历所有节点后返回0。

如果未出现环路,则正常结束遍历并返回1,通过持续累加该函数的返回值,即可得知树的数量!

解法代码


import java.io.*;
import java.util.*;

public class Main {

    public static int dfs(int nowNode, int parent, boolean[] visitLog, HashMap<Integer, ArrayList<Integer>> graph) {

        for (int nextNode : graph.get(nowNode)) {

            if (nextNode != parent && !visitLog[nextNode]) {

                visitLog[nextNode] = true;

                int result = dfs(nextNode, nowNode, visitLog, graph);
                if (result == 0) {
                    return 0;
                }

            } else if (nextNode != parent && visitLog[nextNode]) {
                return 0;
            }

        }

        return 1;

    }

    public static void main(String[] args) throws IOException {

        BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter output = new BufferedWriter(new OutputStreamWriter(System.out));

        int testCase = 0;

        ArrayList<String> outputArr = new ArrayList<>();

        while (true) {

            StringTokenizer treeInfo = new StringTokenizer(input.readLine(), "[ ]");
            int nodeNumber = Integer.parseInt(treeInfo.nextToken());
            int edgeNumber = Integer.parseInt(treeInfo.nextToken());

            if (nodeNumber == 0 && edgeNumber == 0) {
                break;
            }

            testCase += 1;

            int treeCount = 0;
            boolean[] isVisited = new boolean[nodeNumber + 1];

            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("Case ");
            stringBuilder.append(testCase);
            stringBuilder.append(": ");

            HashMap<Integer, ArrayList<Integer>> treeGraph = new HashMap<>();
            for (int i = 1; i < nodeNumber + 1; i++) {
                treeGraph.put(i, new ArrayList<>());
            }

            for (int i = 0; i < edgeNumber; i++) {

                StringTokenizer edgeInfo = new StringTokenizer(input.readLine(), "[ ]");
                int startNode = Integer.parseInt(edgeInfo.nextToken());
                int endNode = Integer.parseInt(edgeInfo.nextToken());

                treeGraph.get(startNode).add(endNode);
                treeGraph.get(endNode).add(startNode);

            }

            for (int i = 1; i < nodeNumber + 1; i++) {

                isVisited[i] = true;
                treeCount += dfs(i, 0, isVisited, treeGraph);
            }

            if (treeCount == 0) {
                stringBuilder.append("No trees.");
            } else if (treeCount == 1) {
                stringBuilder.append("There is one tree.");
            } else if (treeCount > 1) {
                stringBuilder.append("A forest of ");
                stringBuilder.append(treeCount);
                stringBuilder.append(" trees.");
            }

            outputArr.add(stringBuilder.toString());

        }

        for (int i = 0; i < testCase; i++) {

            if (i != testCase - 1) {
                output.write(outputArr.get(i) + "\n");
            } else {
                output.write(outputArr.get(i));
            }

        }

        output.flush();
        output.close();

    }

}

댓글 작성

게시글에 대한 의견을 남겨 주세요.

댓글 0