코테/백준

[백준/JAVA] 2162번: 선분 그룹

imname1am 2023. 5. 18. 22:02
반응형

🔺 문제

 

2162번: 선분 그룹

첫째 줄에 N(1 ≤ N ≤ 3,000)이 주어진다. 둘째 줄부터 N+1번째 줄에는 양 끝점의 좌표가 x1, y1, x2, y2의 순서로 주어진다. 각 좌표의 절댓값은 5,000을 넘지 않으며, 입력되는 좌표 사이에는 빈칸이 하

www.acmicpc.net

 

 

🔺 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import java.util.*;
import java.io.*;
 
public class Main {
    static int[]   parent = new int[3001];   // 부모 노드 저장 배열
    static int[][] L = new int[3001][4];     // 선분 저장 배열
    
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        int N = Integer.parseInt(br.readLine());    // 선분 갯수
        for(int i = 1 ; i <= N ; i++) {
            parent[i] = -1;
        }
        
        // 신규 선분 저장
        for(int i = 1 ; i <= N ; i++) {
            st = new StringTokenizer(br.readLine()," ");
            L[i][0= Integer.parseInt(st.nextToken());
            L[i][1= Integer.parseInt(st.nextToken());
            L[i][2= Integer.parseInt(st.nextToken());
            L[i][3= Integer.parseInt(st.nextToken());
            
            // 이전에 저장된 선분들과 교차 여부 확인
            for(int j = 1 ; j < i ; j++) {
                if(isCross(L[i][0], L[i][1], L[i][2], L[i][3], L[j][0], L[j][1], L[j][2], L[j][3])) {
                    union(i, j);
                }
            }
        }
        
        int ans = 0;    // 선분 그룹 수
        int res = 0;    // 가장 큰 선분 그룹의 선분 수를 음수로 저장하는 변수
        for(int i = 1 ; i <= N ; i++) {
            if(parent[i] < 0) {                 // 음수면, 선분 그룹을 대표 부모 노드
                ans++;                          // 선분 그룹 수 증가
                res = Math.min(res, parent[i]); // 음수의 절댓값이 선분 그룹의 선분 개수
            }
        }
        System.out.println(ans);
        System.out.println(-res);
    }
    
    // 유니온파인드
    static int find(int i) {
        if(parent[i] < 0return i;
        return parent[i] = find(parent[i]);
    }    
    static void union(int a, int b) {
        int p = find(a);
        int q = find(b);
        
        if(p == q)  return;     // 이미 연결됨
        parent[p] += parent[q]; // p의 부모 노드에 q가 속한 선분 그룹의 선분 개수 더하기
        parent[q] = p;          // p를 q의 부모 노드로 저장
    }
    
    // CCW
    private static int CCW(long x1, long y1, long x2, long y2, long x3, long y3) {
        long tmp = (x1*y2 + x2*y3 + x3 * y1) - (x2*y1 + x3*y2 + x1*y3);
        
        if(tmp > 0)      return 1;  // 반시계
        else if(tmp < 0return -1// 시계
        return 0;                   // 일직선
    }
    
    // 선분 겹치는지 판단
    private static boolean isOverlap(long x1, long y1, long x2, long y2, long x3, long y3, long x4, long y4) {
        if(Math.min(x1, x2) <= Math.max(x3, x4) && Math.min(x3, x4) <= Math.max(x1, x2)
        && Math.min(y1, y2) <= Math.max(y3, y4) && Math.min(y3, y4) <= Math.max(y1, y2))
            return true;
        return false;
    }
    
    // 교차 여부 판단
    private static boolean isCross(long x1, long y1, long x2, long y2, long x3, long y3, long x4, long y4) {
        int abc = CCW(x1, y1, x2, y2, x3, y3);
        int abd = CCW(x1, y1, x2, y2, x4, y4);
        int cda = CCW(x3, y3, x4, y4, x1, y1);
        int cdb = CCW(x3, y3, x4, y4, x2, y2);
        
        // 선분이 일직선일 때
        if(abc * abd == 0 && cda * cdb == 0) {
            return isOverlap(x1, y1, x2, y2, x3, y3, x4, y4);
        }
        // 선분이 교차하는 경우
        else if(abc * abd <= 0 && cda * cdb <= 0) {
            return true;
        }
        return false;
    }
}
cs
✅ 해결 아이디어
✔ 분리 집합 & 선분 교차 판정

🔺 다른 풀이들

- 멋진 해설... 

 

[BOJ] 백준 2162번 : 선분 그룹 (JAVA)

문제 N개의 선분들이 2차원 평면상에 주어져 있다. 선분은 양 끝점의 x, y 좌표로 표현이 된다. 두 선분이 서로 만나는 경우에, 두 선분은 같은 그룹에 속한다고 정의하며, 그룹의 크기는 그 그룹

steady-coding.tistory.com

 

[백준] 2162번 선분 그룹 / Java, Python

조금 더 어려운 기하 문제를 풀어 봅시다.Java / Python2162번 선분 교차를 응용하는 문제이번 문제는 N개의 선분들이 주어졌을 때, 이 선분들은 총 몇 개의 그룹으로 되어 있는지, 가장 크기가 큰 그

velog.io


💬 느낀 점

유니온 파인드 오랜만입니다ㅎㅎ

 

 

1회독 2회독 3회독 4회독 5회독
V        

(참고)

✔ Do it 알고리즘 코딩테스트 자바편

 

반응형