티스토리 뷰

알고리즘/백준(BOJ)

백준 - 14868 문명

시나모온 2020. 8. 25. 01:15

문제 링크입니다 : https://www.acmicpc.net/problem/14868

 

14868번: 문명

표준 입력으로 다음 정보가 주어진다. 첫 번째 줄에는 세계의 크기를 나타내는 정수 N(2 ≤ N ≤ 2,000)과 문명 발상지의 수 K(1 ≤ K ≤ 100,000)가 주어진다. 다음 K줄에는 한 줄에 하나씩 문명 발상지�

www.acmicpc.net

유니온 파인드 + dfs 문제였다.

 

생각할 게 좀 은근히 있는 문제라서 좀 어려웠다. ㅠㅠ

 

 

#include <iostream>
#include <vector>
#include <queue>

using namespace std;

const int dy[4] = {0, 0, -1, 1};
const int dx[4] = {-1, 1, 0, 0};

int N, K;
vector<vector<int>> board;
vector<vector<bool>> visited;
vector<int> parent;
int cnt = 0;

int findParent(int a) {
    if(parent[a] == a) return a;
    return parent[a] = findParent(parent[a]);
}

bool unionParent(int a, int b) {
    a = findParent(a);
    b = findParent(b);

    if(a == b) return false;
    else if(a > b) {
        parent[a] = b;
    } else {
        parent[b] = a;
    }
    return true;
}

vector<pair<int, int>> findSomethingStrange(int y, int x) {
    vector<pair<int, int>> ret;
    for(int dir = 0; dir < 4; dir++) {
        int ny = y + dy[dir];
        int nx = x + dx[dir];
        if(ny < 0 || ny >= N || nx < 0 || nx >= N) continue;
        if(board[ny][nx] != 0 && findParent(board[y][x]) != findParent(board[ny][nx])) {
            ret.push_back({ny, nx});
        } else {
            ret.push_back({-1, -1});
        }
    }

    return ret;
}

int bfs(const vector<pair<int, int>>& start) {
    queue<pair<int, int>> q;

    for(int i = 0; i < start.size(); i++) {
        q.push({start[i].first, start[i].second});
        visited[start[i].first][start[i].second] = true;
    }

    int year = 0;

    while(!q.empty()) {
        int qSize = q.size();

        vector<pair<pair<int, int>, int>> newLand;


        // cout << endl;
        // cout << "=============\n";
        // for(int i = 0; i < N; i++) { 
        //     for(int j = 0; j < N; j++) {
        //         cout << board[i][j] << ' ';
        //     }
        //     cout << endl;
        // }

        for(int i = 0; i < qSize; i++) {
            int cy = q.front().first;
            int cx = q.front().second;
            q.pop();



            vector<pair<int, int>> temp = findSomethingStrange(cy, cx);

            for(int j = 0; j < temp.size(); j++) {
                if(temp[j].first != -1 && unionParent(board[cy][cx], board[temp[j].first][temp[j].second])) {
                    cnt++;
                }
            }
            if(cnt == K - 1) return year;

            for(int dir = 0; dir < 4; dir++) {
                int ny = cy + dy[dir];
                int nx = cx + dx[dir];
                if(ny < 0 || ny >= N || nx < 0 || nx >= N) continue;
                if(visited[ny][nx]) continue;
                visited[ny][nx] = true;
                newLand.push_back({{ny, nx}, findParent(board[cy][cx])});
                q.push({ny, nx});
            }
        }

        for(int i = 0; i < newLand.size(); i++) {
            int newy = newLand[i].first.first;
            int newx = newLand[i].first.second;
            int owner = newLand[i].second;
            board[newy][newx] = owner;
        }
        year++;
    }
}

int main() {
    ios_base :: sync_with_stdio(false); 
    cin.tie(NULL); cout.tie(NULL);

    cin >> N >> K;
    board.assign(N, vector<int>(N, 0));
    visited.assign(N, vector<bool>(N, false));
    parent.resize(K + 1);

    vector<pair<int, int>> start;

    int a, b;
    for(int i = 1; i <= K; i++) {
        cin >> a >> b;
        board[a - 1][b - 1] = i;
        parent[i] = i;
        start.push_back({a - 1, b - 1});
    }

    cout << bfs(start);



    return 0;
}

 

 

 

개발 환경 : vscode

지적, 조언, 질문 환영입니다! 댓글 남겨주세요~

 

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

백준 - 11085 군사 이동  (0) 2020.08.25
백준 - 3197 백조의 호수  (0) 2020.08.25
백준 - 16562 친구비  (0) 2020.08.21
백준 - 2075 N번째 큰 수  (0) 2020.08.21
백준 - 1715 카드 정렬하기  (0) 2020.08.21
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2025/04   »
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
글 보관함