developer-ellen
인간 디버거의 로그 찍기
developer-ellen
전체 방문자
오늘
어제
  • 분류 전체보기 (217)
    • 회고록 (0)
    • 취뽀 및 커리어 여정의 Stack (2)
      • SSAFY 7기 (2)
    • 프로그래밍공부 (24)
      • c++ (0)
      • JAVA (3)
      • Spring (5)
      • design pattern (3)
      • BackDB (1)
      • Servlet&JSP (3)
      • Vue (4)
      • JPA (4)
      • Infra (1)
      • Linux (0)
    • AI (3)
      • papers (3)
      • trend (0)
    • 프로젝트진행 (0)
      • 데이터베이스 (0)
      • 서버개발 (0)
      • 인공지능 (0)
      • 하루정리 (0)
    • 포트폴리오 (0)
    • 알고리즘 (158)
      • 알고리즘문풀 (155)
      • 알고리즘공부 (3)
    • 통계공부 (15)
      • 시계열분석 (15)
      • 회귀분석 (0)
    • CS (14)
      • 컴퓨터네트워크 (4)
      • 운영체제 (8)
      • 데이터베이스 (2)
    • 주저리주저리 (0)
      • 필사 (0)
    • 취업관련정보 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • BOJ파이썬풀이
  • 삼성코테구현문제추천
  • c++디자인패턴
  • 삼성코테파이썬풀이
  • 삼성코테기출자바풀이
  • 삼성코테자바준비
  • 코테파이썬
  • 삼성코테준비
  • 시계열
  • SW역량테스트파이썬
  • c++ 빌더 패턴
  • 통계분석
  • 카카오코테
  • 삼성코테자바꿀팁
  • AR모형
  • MA모형
  • 백준파이썬풀이
  • 삼성코테자바풀이
  • ARIMA모형
  • SW역량테스트파이썬풀이
  • 삼성코테파이썬
  • 데이터분석
  • Arima
  • 카카오코테java풀이
  • 삼성코테구현풀이
  • 삼성코테기출
  • 통계학
  • 시계열분석
  • 삼성코테파이썬준비
  • 운영체제인터럽트

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
developer-ellen

인간 디버거의 로그 찍기

알고리즘/알고리즘문풀

BOJ - 비용 2463번 (JAVA)

2022. 7. 23. 22:47

❓ 문제 - 백준 비용 2463번 - JAVA 풀이법

 

출처 

(https://www.acmicpc.net/problem/2463)

 

2463번: 비용

첫 번째 줄에 정점의 수 N (1< ≤ N ≤ 100,000)과 간선의 수 M (1 ≤ M ≤ 100,000)이 빈칸을 사이에 두고 주어진다. 다음 M개의 각 줄에 간선 하나에 대한 정보를 나타내는 세 개의 양의 정수 x,y,w가 빈칸

www.acmicpc.net

 

 

 

📝 문제해결법

1. 문제 해석

  • Cost(u, v)는 u와 v사이에 경로가 있으면 이 그래프의 최소 가중치 간선을 그래프에서 제거하는데 u와 v 사이의 경로가 없을 때까지 반복해서 제거하고, 제거되는 간선의 합을 구한다.
  • u < v인 모든 두 정 점들의 Cost(u, v)들의 총 합을 출력한다.
  • 예를 들어 문제에서 주어진 예시로 cost(2, 6)이라면 정점 2, 6사이에 이어지는 모든 간선들 중 2, 6보다 작은 간선들은 (2,3)-> 3, (4, 3) -> 3,  (3, 5) -> 4, (3, 4) -> 5 이며 이 간선들을 다 제거하고 그 다음 크기의 간선인 2,6까지 지우면 2,6 사이의 경로는 존재하지 않으며, Cost(u, v)는 2+3+4+5+6 = 20으로 구할 수 있다.

 

2. 해결 방법

  • u < v 인 모든 두 정점의 Cost(u, v)의 합을 구할 때, 위 방법의 순서대로 하면 하나하나 다 따지면서 계산해야하므로 복잡하다. 따라서 계산은 역방향으로 진행하며, 모든 간선이 떨어져 있다고 가정하고 최대 간선부터 연결하면서 Cost(u, v)를 계산한다.
  • 우선 간선을 내림차순으로 정렬한 후, 모든 간선의 합을 구한다.
  • 먼저 최대 간선을 연결하고, 간선의 총합을 구한다.
테스트 케이스 예시 1
1) 초기 6개의 정점은 다 분리된 상태에서 시작하며, 모든 간선의 합은 45이다.
2) 먼저 간선의 비용일 기준으로 내림차순을 진행한다.
3) 먼저 최대 간선인 15을 먼저 연결하면 정점 3, 6은 하나의 연결이 되며, union find를 수행해서 서로 같은 부모 3으로 설정한다. Cost(3, 6) = 45이며 이제 남은 간선들의 합은 45-15 = 30이다.
4) 그 다음 최대 간선 10을 연결하면 정점 1, 2는 하나의 연결이 되며 union find를 수행해서 서로 같은 부모 1로 설정한다. Cost(1, 2) = 30이며, 이제 남은 간선들의 합은 30-10 = 20이다.
5) 그 다음 최대 간선 6을 연결하면 1-3 / 1-6 / 2-3 / 2-6 즉 1, 2, 3, 5은 하나로 연결되고 Cost(1, 3) = Cost(1, 6) = Cost(2, 3) = Cost(2, 6) = 20이며 남은 모든 간선의 합은 14이다.
. . .

위 과정을 연결되지 않은 남은 간선이 없을 때까지 반복한다.
  • 위 과정은 Union-Find 방법으로 하며 두 개의 다른 부모를 바라보면 합집합을 수행하고, 두 개의 그룹에 포함된 정점들을 다 모두 이어주고, 이 두 정점수를 곱한 수와 남은 간서의 합을 곱하면서 모든 Cost(u, v)의 합을 구한다.

 

 

3. 삽질 & 느낀점

  • 문제를 40분 넘게 봤는데.. 대충은 이해가 갔는데 어떻게 접근을 해야할지 감이 오지 않았다. 그리고 무언가 연결된 것을 찾아서 값들을 더해주고 하는 것 같아서 Union-Find 방법까지 생각했지만 구현방법을 모르겠었다. 그래서 다른 살마들의 풀이를 보면서 역방향(간선을 이어주는) 방법을 알아냈고 그대로 구현했는데.. 통과했다!
  • 문제에서 나열된 계산방법 그대로 구현하려 할 때 너무 복잡하다면 역방향의 계산 방법 들을 고려해보는 방법도 생각해야할 것 같다.

 

💻 소스코드 

// BOJ - 비용(2463번)
// Union find

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.StringTokenizer;

public class Main_2463 {
    public static int n, m;
    public static int[] parent;
    public static int[] child;

    public static class Edge implements Comparable<Edge>{
        int x;
        int y;
        int cost;
        public Edge(int x, int y, int cost){
            this.x = x;
            this.y = y;
            this.cost = cost;
        }

        @Override
        public int compareTo(Edge o) {
            return o.cost - this.cost;
        }
    }
    public static ArrayList<Edge> list;
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine(), " ");
        n = Integer.parseInt(st.nextToken());
        m = Integer.parseInt(st.nextToken());
        long sum = 0;
        list = new ArrayList<>();
        for(int i=0;i<m;i++){
            st = new StringTokenizer(br.readLine(), " ");
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());
            int c = Integer.parseInt(st.nextToken());
            sum += c;
            list.add(new Edge(Math.min(a, b), Math.max(a, b), c));
        }
        parent = new int[n+1];
        child = new int[n+1];

        for(int i=1;i<=n;i++){
            parent[i] = i;
            child[i] = 1;
        }

        long answer = 0;
        Collections.sort(list);

        for(Edge edge:list){
           answer += sum * union(edge.x, edge.y);
           answer %= 1000000000;
           sum -= edge.cost;
        }

        System.out.println(answer);

    }

    public static int find_parent(int x){
        if(parent[x] == x) return x;
        return parent[x] = find_parent(parent[x]);
    }

    public static long union(int a, int b){
        int parentA = find_parent(a);
        int parentB = find_parent(b);
        if(parentA == parentB) return 0;
        parent[parentB] = parentA;
        long cnt = (long) child[parentA] * child[parentB];
        child[parentA] += child[parentB];
        child[parentB] = 0;
        return cnt;

    }

}

 

 

 

'알고리즘 > 알고리즘문풀' 카테고리의 다른 글

BOJ - 숫자구슬 2613번 (JAVA)  (0) 2022.07.30
BOJ - RBY팡! 5577번 (JAVA)  (0) 2022.07.27
BOJ - 로봇 청소기 4991번 (JAVA)  (0) 2022.07.21
BOJ - 싸지방에 간 준하 12764번 (JAVA)  (0) 2022.07.19
BOJ - 택배 1719번 (JAVA)  (0) 2022.07.18
    '알고리즘/알고리즘문풀' 카테고리의 다른 글
    • BOJ - 숫자구슬 2613번 (JAVA)
    • BOJ - RBY팡! 5577번 (JAVA)
    • BOJ - 로봇 청소기 4991번 (JAVA)
    • BOJ - 싸지방에 간 준하 12764번 (JAVA)
    developer-ellen
    developer-ellen

    티스토리툴바