Notice
Recent Posts
Recent Comments
Link
«   2026/06   »
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
관리 메뉴

dh-winternagi 님의 블로그

(17472) 다리 만들기 2 본문

백준 (C++)/Solve

(17472) 다리 만들기 2

dh-winternagi 2026. 4. 20. 19:42

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

단계별로 풀어보기

35단계(최소 신장 트리) 6번째

 

 

 

정점과 간선을 구하는 것이 매우 복잡하다는 점만 빼면, 평범한 MST 문제다.

섬의 개수가 최대 6개이므로 유니온 파인드는 하드코딩으로 전처리 했다.

정점과 간선을 구하는 과정은 구현, 시뮬레이션 파트에 가까우니 생략한다.

 

 

 

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef pair<int, pair<int, int>> edge;

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
  
  int n, m;
  
  cin >> n >> m;
  
  vector board(n+2, vector<int> (m+2));
  
  vector<int> uf= {0, 1, 2, 3, 4, 5, 6, 7};
  vector<edge> v;
  
  for(int i=1;i<=n;i++){
    for(int j=1;j<=m;j++){
      cin >> board[i][j];
    }
  }
  
  auto dfs= [&](auto self, int x, int y, int t) -> void {
    board[x][y]= t;
    
    if(board[x-1][y]==1)  self(self, x-1, y, t);
    if(board[x+1][y]==1)  self(self, x+1, y, t);
    if(board[x][y-1]==1)  self(self, x, y-1, t);
    if(board[x][y+1]==1)  self(self, x, y+1, t);
  };
  
  int num= 1;
  
  for(int i=1;i<=n;i++){
    for(int j=1;j<=m;j++){
      if(board[i][j]==1){
        dfs(dfs, i, j, ++num);
      }
    }
  }
  
  for(int i=1;i<=n;i++){
    for(int j=1;j<=m;j++){
      if(board[i][j]){
        int len=0;
        while(1){
          len++;
          if(i==len)  break;
          
          if(board[i-len][j]){
            if(len>2){
              v.push_back({len-1,{board[i][j],board[i-len][j]}});
            }
            break;
          }
        }

        len=0;
        while(1){
          len++;
          if(j==len)  break;
          
          if(board[i][j-len]){
            if(len>2){
              v.push_back({len-1,{board[i][j],board[i][j-len]}});
            }
            break;
          }
        }
      }
    }
  }
  
  sort(v.begin(), v.end());
  
  auto find= [&](auto self, int x) -> int {
    if(uf[x]==x)  return x;
    else  return uf[x]= self(self, uf[x]);
  };
  
  auto merge= [&](int x, int y){
    x= find(find, x);
    y= find(find, y);
    
    if(x==y)  return false;
    
    uf[y]= x;
    
    return true;
  };
  
  int cnt= 1, ans= 0;
  
  for(edge elem:v){
    if(merge(elem.second.first, elem.second.second)){
      cnt++;
      ans+= elem.first;
      
      if(cnt==num-1)  break;
    }
  }
  
  cout << (cnt==num-1 ? ans : -1);
  
  return 0;
}

'백준 (C++) > Solve' 카테고리의 다른 글

(1949) 우수 마을  (0) 2026.04.20
(15681) 트리와 쿼리  (0) 2026.04.20
(6497) 전력난  (0) 2026.04.20
(1774) 우주신과의 교감  (0) 2026.04.20
(4386) 별자리 만들기  (0) 2026.04.20