[BOJ 4803, Java] 树
BOJ 4803,“树”题的 Java 解法
题目链接
[BOJ 4803](https://www.acmicpc.net/problem/4803
)
分类
数据结构(data_structures)、深度优先搜索(dfs)、不相交集合(disjoint_set)、图论(graphs)、图遍历(graph_traversal)、树(trees)
说明
这是一道利用树的性质来统计树的数量的问题。本题可以通过排除由连接元素构成的结构中的环来解决。
- 检查所有节点是否已被访问
- 对于未访问的节点,将其纳入树中并进行深度遍历
- 若形成环,则将构成该环的所有节点标记为已访问
- 若未形成环,则该集合为树,计数为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();
}
}
댓글 작성
게시글에 대한 의견을 남겨 주세요.