WUSTOJ 1318: 区间的连通性(Java)
题目链接:🔗1318: 区间的连通性
参考博客:🔗wust oj 1318 区间的连通性(贪心)——wust_zwl的博客
Description
题目包含多组数据,你有一个集合,该集合的元素为形如(x,y)的区间,两个区间1:(a,b)、2:(c,d),如果c < a < d或者c < b < d说明1号区间能到达2号区间,当然如果2号区间能到3号区间的话,那么1号区间也能到达3号区间。(该性质具有传递性)
现在给你n个操作,操作分为两种:
1.“1 x y”(x < y),将区间加入集合中。(区间按照加入的顺序编号)
2.“2 a b”(a != b),问你第a个区间能否到达第b个区间。
Input
首先是一个n(1<=n<=200),表示操作数,然后有n行,每行有三个数,代表一个操作。
输入保证数据都在10^9的范围内。
Output
第2种操作时,如果a能到达b,输出“YES”,否则输出“NO”(不带引号)。
Sample Input
5
1 1 5
1 5 11
2 1 2
1 2 9
2 1 2
Sample Output
NO
YES
分析💬
- 显然区间端点需要保存,用
int
型的二维数组collection[201][2]
即可。 - 不同区间之间是否连通,直接用
boolean
型的二维数组connected[opNum + 1][opNum + 1]
表示。 - 操作1,将区间端点保存到
collection
中,并设置connected
对应的能直接连通的值为true
- 操作2,判断区间
a
和区间b
是否连通,如果连通,直接输出YES
,如果不连通,设置connected
对应的能间接连通的值为true
,然后再次判断是否连通,输出YES
或者NO
。
易错点:不要想着统一输入完后,再输出。就拿Simple Input来说,会输出两个YES
。
代码
/**
* Time 711ms
* @author wowpH
* @version 2.4
* @date 2019年6月21日下午5:09:32
* Environment: Windows 10
* IDE Version: Eclipse 2019-3
* JDK Version: JDK1.8.0_112
*/
import java.io.InputStreamReader;
import java.util.Scanner;
public class Main {
private int intervalNum;// 操作1的次数,也就是区间的个数
// 集合,存储区间的端点,下标从1开始
private int[][] collection = new int[201][2];
private boolean[][] connected;// 存储区间是否连通
private int a, b;// 操作的后两个数
public Main() {
Scanner sc = new Scanner(new InputStreamReader(System.in));
int opNum, flag;// 总操作次数,操作类型(1或2)
while (sc.hasNext()) {
intervalNum = 0;// 初始化区间的个数
opNum = sc.nextInt();// 总的操作次数
connected = new boolean[opNum + 1][opNum + 1];// 存储区间是否连通
for (int i = 0; i < opNum; ++i) {
flag = sc.nextInt();// 操作类型
a = sc.nextInt();
b = sc.nextInt();
if (1 == flag) {
opOne();// 操作1
} else {
opTwo();// 操作2
}
}
}
sc.close();
}
// 操作1
private void opOne() {
++intervalNum;
collection[intervalNum][0] = a;// 保存区间端点
collection[intervalNum][1] = b;
directlyConnected();// 直接连通
}
// 操作2
private void opTwo() {
if (true == connected[a][b]) {
System.out.println("YES");// 区间b与区间c连通
} else {
indirectlyConnected();// 间接连通
if (true == connected[a][b]) {
System.out.println("YES");
} else {
System.out.println("NO");
}
}
}
// 直接连通
private void directlyConnected() {
for (int j = 1; j < intervalNum; ++j) {// 遍历前面的intervalNum-1个区间
// 区间intervalNum可以到区间j
if (collection[j][0] < a && a < collection[j][1]
|| collection[j][0] < b && b < collection[j][1]) {
connected[intervalNum][j] = true;
}
// 区间j可以到区间intervalNum
if (a < collection[j][0] && collection[j][0] < b
|| a < collection[j][1] && collection[j][1] < b) {
connected[j][intervalNum] = true;
}
}
}
// 间接连通
private void indirectlyConnected() {
// 遍历所有区间,作为中间区间
for (int center = 1; center <= intervalNum; ++center) {
// 遍历所有区间,作为左边区间
for (int left = 1; left <= intervalNum; ++left) {
if (false == connected[left][center]) {
continue;// 区间left和区间center不连通,继续下一个区间
}
// 区间left和区间center连通,遍历所有区间,作为右边区间
for (int right = 1; right <= intervalNum; ++right) {
// 区间center和right连通
if (true == connected[center][right]) {
connected[left][right] = true;// 传递性
}
}
}
}
}
public static void main(String[] args) {
new Main();
}
}