Notice
Recent Posts
Recent Comments
Link
«   2024/09   »
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
Archives
Today
Total
관리 메뉴

Life Engineering

[BOJ 17427] 다리 만들기 (C++) 본문

Problem Solving

[BOJ 17427] 다리 만들기 (C++)

흑개 2021. 8. 26. 15:54

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

 

17472번: 다리 만들기 2

첫째 줄에 지도의 세로 크기 N과 가로 크기 M이 주어진다. 둘째 줄부터 N개의 줄에 지도의 정보가 주어진다. 각 줄은 M개의 수로 이루어져 있으며, 수는 0 또는 1이다. 0은 바다, 1은 땅을 의미한다.

www.acmicpc.net

 

#include <bits/stdc++.h>

using namespace std;
int graph[11][11];
bool visited[11][11];
int parents[7];
int N, M;
int dy[4]={-1,1,0,0};
int dx[4]={0,0,-1,1};

class Node{
    public:
        int start;
        int end;
        int cost;
        Node(int start, int end, int cost){
            this->start=start;
            this->end=end;
            this->cost=cost;
        }
};

struct compare{
    bool operator()(Node a, Node b){
        return a.cost>b.cost;
    }
};

priority_queue<Node, vector<Node>, compare> pq;

bool isPossible(int y, int x){
    if (y<0 || x<0 || y>=N || x>=M){
        return false;
    }
    else{
        return true;
    }
}

void findBridge(int start,int y, int x, int dy, int dx){
    int cnt=1;
    int num=0;
    while (isPossible(y+dy, x+dx) && graph[y+dy][x+dx]==0){     //벽을 만나거나 1을 만나면 나가리
        cnt++;
        //num=graph[y+dy][x+dx];
        y+=dy;
        x+=dx;
    }
    if (isPossible(y+dy, x+dx) && graph[y+dy][x+dx]!=0 && cnt>=2){
        num=graph[y+dy][x+dx];
        pq.push(Node(start,num,cnt));
    }
}

void bfs(int y, int x, int num){
    queue<pair<int,int> > q;
    q.push(make_pair(y,x));
    graph[y][x]=num;
    visited[y][x]=true;
    while (!q.empty()){
        int row=q.front().first;
        int col=q.front().second;
        q.pop();
        for (int i=0; i<4; i++){
            int nrow=row+dy[i];
            int ncol=col+dx[i];
            if (isPossible(nrow,ncol) && graph[nrow][ncol]==1){
                if (!visited[nrow][ncol]){
                    q.push(make_pair(nrow,ncol));
                    graph[nrow][ncol]=num;
                    visited[nrow][ncol]=true;
                }
            }
        }
    }
}

int find(int x){
    if (parents[x]==x){
        return x;
    }
    return parents[x]=find(parents[x]);
}

void union_(int a, int b){
    int pa=find(a);
    int pb=find(b);
    if (pa!=pb){
        parents[pa]=pb;
    }
}

int main(){
    int x;
    cin>>N>>M;
    vector<pair<int,int> > ones;
    int num=1;      //섬의 개수
    int ans=0;
    int cnt=0;
    for (int i=0; i<7; i++){
        parents[i]=i;
    }
    for (int i=0; i<N; i++){
        for (int j=0; j<M; j++){
            cin>>x;
            graph[i][j]=x;
            visited[i][j]=false;
            if (x==1){
                ones.push_back(make_pair(i,j));
            }
        }
    }
    for (int i=0; i<ones.size(); i++){
        int y=ones[i].first;
        int x=ones[i].second;
        if (!visited[y][x]){
            bfs(y,x,num);
            num++;
        }
    }
    num-=1;
    for (int i=0; i<ones.size(); i++){
        int y=ones[i].first;
        int x=ones[i].second;
        int start=graph[y][x];
        for (int j=0; j<4; j++){
            int ny=y+dy[j];
            int nx=x+dx[j];
            if (isPossible(ny,nx) && graph[ny][nx]==0){
                findBridge(start,ny,nx,dy[j],dx[j]);
            }
        }
    }
    while (!pq.empty()){
        Node now=pq.top();
        pq.pop();
        int nowstart=now.start;
        int nowend=now.end;
        if (find(nowstart)!=find(nowend)){
            union_(nowstart,nowend);
            cnt++;
            ans+=now.cost;
        }
        if (cnt==num-1){
            break;
        }
    }
    if (cnt<num-1){             //모두 잇는 경우가 없을때!!(이 조건 중요)
        ans=-1;
    }
    cout<<ans<<"\n";  
    return 0;
}

모두 잇는 경우가 없을 때 판정하는 조건문이 필수였다.

'Problem Solving' 카테고리의 다른 글

[프로그래머스] 오픈채팅방 (C++)  (0) 2021.08.30
[프로그래머스] 문자열 압축 (C++)  (0) 2021.08.30
[BOJ 7578] 공장 (C++)  (0) 2021.08.20
[BOJ 1238] 파티 (C++)  (0) 2021.08.19
[BOJ 17070] 파이프 옮기기 (C++)  (0) 2021.08.19