z BOJ 2162. 선분 그룹 :: C++, 그래픽 기술 블로그

BOJ 2162. 선분 그룹

랭크 : 플레티넘4

문제 풀이

2개의 선분이 주어졌을 때, 한 선분에서 다른 선분의 요소에 대해서 외적을 취하여 이들의 부호가 -라면 각각 다른 방향에 존재하고, +라면 같은 방향에 존재하기 때문에, -임을 확인하면 됩니다. 이를 양쪽 선분에 대해서 모두 수행하고, 만약 같은 선상에 있어 외적이 0이라면, 두 선분 사이에 점이 존재하는지 안하는 지를 확인하여, 이후에 union-find를 통해 그룹을 나누어 정리하면 됩니다.
제출 했을 때 틀린 부분은, 먼저 자료형 long long으로 해주는 부분과, 한 선분 위에 점 4개가 있을 때 x좌표로만 비교를 해주었는데, x좌표가 동일하고 y좌표만 다른 경우가 존재해 이런 경우 처리를 따로 해주었습니다.


#include <bits/stdc++.h>
#define fastio cin.tie(0)->sync_with_stdio(0)

using namespace std;
struct Point {
    long long x;
    long long y;
    Point() : x(0), y(0) {};
    Point(long long _x, long long _y) : x(_x), y(_y) {};
    Point operator-(const Point& ref) {
        return Point(ref.x - x, ref.y - y);
    }
    long long operator*(const Point& ref) {
        return ref.x * y - x * ref.y;
    }
};
Point lines[3001][2];
long long parents[3001];
long long num[3001];
long long visited[3001];
long long N;

long long CrossProduct(Point x, Point y, Point z) {
    return (x - y) * (x - z);
};

bool CCW(Point x1, Point x2, Point y1, Point y2) {
    long long result1 = CrossProduct(x1, x2, y1) * CrossProduct(x1, x2, y2);
    long long result2 = CrossProduct(y1, y2, x1) * CrossProduct(y1, y2, x2);
    if (result1 == 0 && result2 == 0) {
        if (x1.x != x2.x) {
            long long minx = min(x1.x, x2.x);
            long long miny = min(y1.x, y2.x);
            if (minx <= miny) {
                if (minx <= miny && miny <=  max(x1.x, x2.x)) return true;
            } else {
                if (miny <= minx && minx <=  max(y1.x, y2.x)) return true;
            }
        } else {
            long long minx = min(x1.y, x2.y);
            long long miny = min(y1.y, y2.y);
            if (minx <= miny) {
                if (minx <= miny && miny <=  max(x1.y, x2.y)) return true;
            } else {
                if (miny <= minx && minx <=  max(y1.y, y2.y)) return true;
            }
        }
        return false;
    } else if (result1 <= 0 && result2 <= 0) {
        return true;
    }
    return false;
}

long long FindParents(long long a) {
    if (parents[a] == a) return a;
    return parents[a] = FindParents(parents[a]);
};

void isUnion(long long a, long long b) {
    a = FindParents(a);
    b = FindParents(b);

    if (a == b) return;

    num[b] += num[a];
    num[a] = num[b];
    // 더 작은 값이 부모 노드가 될 수 있도록
    if (a < b) {
        parents[b] = a;
    }
    else {
        parents[a] = b;
    }
}

bool UnionFind(long long a, long long b) {
    a = FindParents(a);
    b = FindParents(b);
    return (a == b);
}

int main() {
    fastio;
    long long tmp1, tmp2, tmp3, tmp4;
    cin >> N;

    for (long long i=0; i < N; i++) {
        cin >> tmp1 >> tmp2 >> tmp3 >> tmp4;
        lines[i][0].x = tmp1;
        lines[i][0].y = tmp2;
        lines[i][1].x = tmp3;
        lines[i][1].y = tmp4;
        num[i] = 1;
        parents[i] = i;
    }

    for (long long i= 0; i < N - 1; i++) {
        for (long long j= i + 1; j < N; j++) {
            if (CCW(lines[i][0], lines[i][1], lines[j][0], lines[j][1])) {
                isUnion(i, j);
            }
        }
    }

    long long group_num = 0;
    for (long long i=0; i < N; i++) {
        long long tmp = FindParents(i);
        if (visited[tmp] == 0) {
            group_num++; visited[tmp]++;
        }
    }
    cout << group_num << endl;
    cout << *max_element(num, num + N) << endl;
}

 

알고리즘 시간복잡도 공간복잡도
union_find O(N^2) O(N)



'알고리즘 > 백준' 카테고리의 다른 글

BOJ 2887. 행성 터널  (0) 2022.07.07
BOJ 1007. 벡터 매칭  (0) 2022.07.07
BOJ 2623. 음악프로그램  (0) 2022.07.06
BOJ 17387. 선분 교차2  (0) 2022.07.06
BOJ 2342. Dance Dance Revolution  (0) 2022.07.06

+ Recent posts