baekjoon

14868번 문명

gokimkh 2022. 5. 10. 16:05

https://www.acmicpc.net/problem/14868

 

14868번: 문명

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

www.acmicpc.net

 

bfs + UF문제이다.

백조의 호수와 비슷한 문제다.

 

1. 문명이 생기는 곳 모두 문명의 값으로 바꿔주었고 queue에 넣어줬다.

2. 담긴 queue를 하나씩 돌면서 값이 있고 자신의 값이랑 다른 문명과 Union을 하였다.

 

#include <bits/stdc++.h>
#define all(v) v.begin(), v.end()
#define INF 2e9
#define F first
#define S second
using namespace std;

typedef long long l;
typedef pair<int,int> p;
typedef tuple<int,int,int> tu;
typedef vector<int> vc;

int board[2001][2001],root[100001];
int dx[] = {1,-1,0,0},dy[] = {0,0,1,-1};

int Find(int x){
    if(root[x] == x) return x;
    else return root[x] = Find(root[x]);
}

void Union(int x,int y){
    x = Find(x), y = Find(y);

    if(x == y) return;
    else if(x < y) root[y] = x;
    else root[x] = y;
}

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

    queue<p> q,temp;
    int n,k,x,y,ans = 0;

    cin >> n >> k;

    for(int i=1;i<=100000;i++)
        root[i] = i;

    auto civ = [&](){
        while(!q.empty()){
            auto cur = q.front();q.pop();

            for(int i=0;i<4;i++){
                int nx = dx[i] + cur.F, ny = dy[i] + cur.S;

                if(nx <= 0 || ny <= 0 || nx > n || ny > n) continue;

                if(!board[nx][ny]){
                    board[nx][ny] = board[cur.F][cur.S];
                    temp.push({nx,ny});
                }
                else{
                    if((board[cur.F][cur.S] == board[nx][ny]) || (Find(board[cur.F][cur.S]) == Find(board[nx][ny])))
                        continue;

                    Union(board[cur.F][cur.S],board[nx][ny]);
                    k--;
                }
            }
        }
    };

    auto Merge = [&](){
        while(!temp.empty()){
            auto cur = temp.front();
            q.push(cur);
            temp.pop();

            for(int i=0;i<4;i++){
                int nx = dx[i] + cur.F, ny = dy[i] + cur.S;

                if(nx <= 0 || ny <= 0 || nx > n || ny > n || !board[nx][ny]) continue;

                if((board[cur.F][cur.S] == board[nx][ny]) || (Find(board[cur.F][cur.S]) == Find(board[nx][ny])))
                    continue;

                Union(board[cur.F][cur.S],board[nx][ny]);
                k--;
            }
        }
    };

    for(int i=1;i<=k;i++){
        cin >> x >> y;

        board[x][y] = i;
        q.push({x,y});
        temp.push({x,y});
    }

    while(1) {

        Merge();

        if(k == 1){
            cout << ans;
            return 0;
        }
        civ();
        ans++;
    }
}