Skip to content

Commit f77bafd

Browse files
committed
feat: add 2018fall/lab8-1075
Signed-off-by: Certseeds <51754303+Certseeds@users.noreply.github.com>
1 parent 1e1cc3c commit f77bafd

File tree

11 files changed

+501
-0
lines changed

11 files changed

+501
-0
lines changed

2018fall/lab_7/lab_7_1073/src/Main.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// SPDX-License-Identifier: AGPL-3.0-or-later
2+
// SPDX-FileCopyrightText: 2018-2025 nanoseeds
23

34
import java.io.BufferedReader;
45
import java.io.IOException;

2018fall/lab_8/README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# 2018fall-lab8
2+
3+
Welcome to (autumn) DSAA lab 8! Enjoy this Lab!
4+
5+
There are seven problems for you to solve. Two of them are bonus. Read the problem description carefully.
6+
7+
Compulsory problems:
8+
9+
+ A(easy): 10
10+
+ B(easy): 10
11+
+ C(easy): 10
12+
+ D(easy): 10
13+
+ E(easy): 10
14+
+ F(median): 25
15+
+ G(median): 25
16+
+ Bonus problem: H(hard): 30
17+
+ Bonus problem: I(hard): 30
18+
19+
Read the samples carefully can help you understand the problem.
20+
21+
## Stack And Queue
22+
23+
+ [x] problem A: lab_8_1074 源码丢失, 无法访问
24+
+ [x] problem B: lab_8_1075
25+
+ [x] problem C: lab_8_1123 源码丢失, 无法访问
26+
+ [ ] problem D: lab_8_1124
27+
+ [ ] problem E: lab_8_1125
28+
+ [ ] problem F: lab_8_1127
29+
+ [x] problem G: lab_8_1126 源码丢失, 无法访问
30+
+ [ ] problem H: lab_8_1128
31+
+ [ ] problem I: lab_8_1130
32+
33+
## 总体评价
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
## Description
2+
3+
In a graph G, if we can find a path from node x to node y, we say that x can reach y. Now you are given a directed graph G with n nodes and m edges. Besides, there are Q queries. Each query will contain two integers x and y. If x can reach y, print YES. Otherwise, print NO.
4+
5+
Note: We guarantee there is at most one edge from node i to node j.
6+
7+
### Input
8+
9+
The first line will be an integer T (1 <= T <= 50). T is the number of test case.
10+
11+
For each test case, the first line will be two integers n and m. (1 <= n <= 1000, 0 <= m <= min(n * n, 100000))
12+
13+
Then there will be m lines. Each line will have two integers x, y. "x y" means there is an edge from x to y.
14+
15+
After that, there is an integer Q. (1 <= Q <= 500) The following are Q lines. Each line will have two integers x, y.
16+
17+
All nodes are labeled from 1 to n.
18+
19+
### Output
20+
21+
For each query, if x can reach y, print YES. Otherwise, print NO.
22+
23+
### Sample Input
24+
25+
```log
26+
1
27+
7 7
28+
1 6
29+
6 4
30+
4 3
31+
3 5
32+
5 1
33+
2 7
34+
7 2
35+
6
36+
1 2
37+
2 7
38+
7 2
39+
3 6
40+
4 6
41+
5 4
42+
```
43+
44+
### Sample Output
45+
46+
```log
47+
NO
48+
YES
49+
YES
50+
YES
51+
YES
52+
YES
53+
```
54+
55+
### HINT
56+
57+
For the first sample, 1 cannot reach 2, because 2 and 7 form a ring.
58+
59+
For the second sample, 2 can reach 7 directly.
60+
61+
For the third sample, 3 -> 5 -> 1 -> 6 is one path.
62+
63+
### 解答 (Solution)
64+
65+
下面给出一种适用于本题约束的实现思路与要点说明(按读-处理-输出分离的风格),供参考与学习:
66+
67+
1) 思路概述
68+
69+
- 由于题目给出的 n 上界为 1000,预计算所有点对的可达性是可行的。实现方法是对每个节点维护一个 BitSet 表示它能到达的所有节点,然后进行基于 BitSet 的传递闭包(Warshall-like)运算:
70+
- 初始化:对每个节点 i,令 `reach[i].set(i)`(节点可到达自身),并把所有有向边 u->v 设为 `reach[u].set(v)`
71+
- 传递闭包:按 k 从 0 到 n-1 遍历,对每个 i 如果 `reach[i].get(k)` 为真,则执行 `reach[i].or(reach[k])`。这一步使用 BitSet 的按字并行操作,速度远快于逐位循环。
72+
- 回答查询:对于每个查询 (x,y) 只需检查 `reach[x].get(y)` 即可,时间 O(1)。
73+
74+
2) 读-处理-输出分离(实现结构)
75+
76+
- `reader()`:使用快速读取(BufferedReader + StringTokenizer)读取 T、每个用例的 n、m、m 条边、Q 以及 Q 条查询;将节点索引转换为 0-based 并做基本的断言检查。
77+
- `cal()`:构建 `BitSet[] reach` 并执行上述传递闭包,最后把每个查询的结果转换为 "YES" 或 "NO" 字符串并收集到结果列表。
78+
- `output()`:一次性把所有结果行输出,保证每行以换行符结尾。
79+
80+
3) 复杂度分析
81+
82+
- 时间复杂度:三重循环的位运算实现,粗略为 O(n^3 / W) 的位操作(W 为机器字长,通常 64),实测在 n ≤ 1000 的约束下非常快。
83+
- 空间复杂度:O(n^2) 位,即 O(n^2 / 8) 字节外加 BitSet 对象开销。对于 n ≤ 1000 是可接受的。
84+
85+
4) 边界与正确性要点
86+
87+
- 请确保在初始化时设置 `reach[i].set(i)`,使得查询 (x,x) 返回 YES(长度为 0 的路径)。
88+
- 输入中的节点编号以 1..n 给出,内部实现要转换为 0-based 来索引数组与 BitSet。
89+
- 对于非法边或查询索引(若存在),应做好范围检查以避免异常;本实现使用了 guard 条件来忽略越界边并在查询时返回 NO。
90+
91+
5) 可替代方案与优化
92+
93+
- 若 n 远大于 1000,则需要替代方法:例如对图先做强连通分量 (SCC) 压缩成 DAG,DAG 节点数通常远小于 n,再在 DAG 上做 BitSet 传递闭包或对每个查询做 BFS/DFS。
94+
- SCC + DAG 方法适用于高密度或有大量互联的图。
95+
- 若 Q 很小而 n 较大,则可以对每个查询直接做 BFS/DFS,复杂度为 O(Q*(n+m)),在 Q 很小的情形下更节省。

2018fall/lab_8/lab_8_1075/pom.xml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<parent>
7+
<groupId>nanoseeds.algorithm-template.2018fall</groupId>
8+
<artifactId>lab_8</artifactId>
9+
<version>${revision}</version>
10+
<relativePath>./../pom.xml</relativePath>
11+
</parent>
12+
<groupId>nanoseeds.algorithm-template.2018fall.lab_7</groupId>
13+
<artifactId>lab_8_1075</artifactId>
14+
<version>${revision}</version>
15+
<name>${project.groupId}.${project.artifactId}</name>
16+
<description>${project.groupId}.${project.artifactId}</description>
17+
18+
<build>
19+
<sourceDirectory>${project.basedir}/src</sourceDirectory>
20+
<testSourceDirectory>${project.basedir}/test</testSourceDirectory>
21+
</build>
22+
</project>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
1
2+
7 7
3+
1 6
4+
6 4
5+
4 3
6+
3 5
7+
5 1
8+
2 7
9+
7 2
10+
6
11+
1 2
12+
2 7
13+
7 2
14+
3 6
15+
4 6
16+
5 4
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
NO
2+
YES
3+
YES
4+
YES
5+
YES
6+
YES

0 commit comments

Comments
 (0)