티스토리 뷰
https://www.acmicpc.net/problem/23034
23034번: 조별과제 멈춰!
교수님이 시험 기간에 조별 과제를 준비하셨다...! 가톨릭대학교의 조교 아리는 N명의 학생을 2개의 조로 구성하여 과제 공지를 하려 한다. 이때, 구성된 각 조의 인원은 1명 이상이어야 한다. 각
www.acmicpc.net
문제
교수님이 시험 기간에 조별 과제를 준비하셨다...! 가톨릭대학교의 조교 아리는 N명의 학생을 2개의 조로 구성하여 과제 공지를 하려 한다. 이때, 구성된 각 조의 인원은 1명 이상이어야 한다. 각 학생은 1~N의 정수 중 고유한 번호를 학번으로 갖는다.
모든 것이 귀찮은 아리는 각 조의 팀장에게만 공지를 전달한다. 아리는 N명의 학생 사이에 있는 총 M개의 회선의 리스트를 가지고 있다. 리스트에는 각 회선에 연결된 두 학생의 학번 A와 B, 연락에 필요한 비용 C가 적혀있다. 회선이 연결된 두 학생은 서로 연락이 가능하다. 아리가 각 팀장에게 공지를 전달하면, 각 팀장과 공지를 알게 된 팀원은 같은 조의 모든 팀원에게 공지 내용을 회선을 통해서만 전달한다. 어떤 학생이 팀장이 되어도 모든 학생은 공지 내용을 전달받을 수 있다.
아리는 공지 채팅방을 만들 생각은 안 하고, 모든 학생이 공지 내용을 알게 될 때까지 학생들이 연락하며 소요되는 비용의 총합 T의 최솟값을 알고 싶어졌다. 그것을 구하여 팀장을 정한 뒤 조를 구성하려고 한다.
아리는 다음과 같은 Q개의 질문을 한다.
- X Y : X와 Y가 팀장일 때, T의 최솟값은 무엇인가?
Q개의 질문에 답할 수 있는 프로그램을 작성하시오.
유형 : MST + 그래프 탐색
접근 방식
- 문제를 이해하는 과정에서 조금의 노력이 필요하다.
- '어떤 학생이 팀장이 되어도 모든 학생은 공지 내용을 전달받을 수 있다.' 라는 말이 의미하는 것은 어느 지점에서라도 다른 지점으로의 경로가 존재하고 해당 값들이 최소여야 하는 것이다. 즉 MST다.
- MST를 만들면서 해당 간선들로 그래프를 만든다.
- 두 지점이 팀장이 된다면 어떤 변화가 발생할까?
- 답은 간단하다. 해당 두 지점 간의 경로에 있어 가장 길이가 긴(최장 경로)의 값이 빠진다.
- 즉 MST로 만들어진 그래프에서 DP[i][j]를 통해 i지점에서 j지점으로 갈 때 최장 길이의 간선 값을 저장한다.
전체 코드
import java.util.*;
import java.io.*;
public class Main {
static int n = 0;
static int m = 0;
static ArrayList<Node>[] graph;
static int[] root;
static int[][] dp;
public static void main(String[] args) throws Exception {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(bf.readLine(), " ");
StringBuilder sb = new StringBuilder();
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
root = new int[n+1];
graph = new ArrayList[n+1];
dp = new int[n+1][n+1];
for(int i=1;i<=n;i++){
root[i] = i;
graph[i] = new ArrayList<>();
}
PriorityQueue<Point> pq = new PriorityQueue<>(
(x,y) -> x.c - y.c
);
for(int i=1;i<=m;i++){
st = new StringTokenizer(bf.readLine(), " ");
int v1 = Integer.parseInt(st.nextToken());
int v2 = Integer.parseInt(st.nextToken());
int c = Integer.parseInt(st.nextToken());
pq.add(new Point(v1,v2,c));
}
int count = 0;
int total = 0;
// MST 생성
while(!pq.isEmpty()){
Point cur = pq.poll();
// Union - Find
if(find(cur.v1) != find(cur.v2)){
union(cur.v1,cur.v2);
total += cur.c; // 총량 계산
count += 1;
graph[cur.v1].add(new Node(cur.v2,cur.c));
graph[cur.v2].add(new Node(cur.v1,cur.c)); // 선택된 간선으로 그래프 구성
}
if(count == n-1) // MST는 n-1개의 간선을 가진다.
break;
}
for(int i=1;i<=n;i++){
bfs(i); // BFS로 각 정점으로부터 모든 정점까지 거리 중 최장 간선 값을 DP 테이블에 저장
}
st = new StringTokenizer(bf.readLine(), " ");
int k = Integer.parseInt(st.nextToken());
for(int i=1;i<=k;i++){
st = new StringTokenizer(bf.readLine(), " ");
int x1 = Integer.parseInt(st.nextToken());
int x2 = Integer.parseInt(st.nextToken());
sb.append(total - dp[x1][x2]); // 계산
sb.append("\n");
}
System.out.print(sb);
bf.close();
}
static void bfs(int s){
Queue<Node> q = new LinkedList<>();
boolean[] v = new boolean[n+1];
q.add(new Node(s,0));
v[s] = true;
while(!q.isEmpty()){
Node cur = q.poll();
for(Node next : graph[cur.v]){
if(!v[next.v]){
v[next.v] = true;
dp[s][next.v] = Math.max(cur.c,next.c); // 출발지점으로부터 도착지점까지 최장 거리 간선 갱신
q.add(new Node(next.v,dp[s][next.v]));
}
}
}
}
static int find(int x){
if(x == root[x])
return root[x];
return root[x] = find(root[x]);
}
static void union(int x,int y){
x = find(x);
y = find(y);
if(x < y)
root[y] = x;
else
root[x] = y;
}
}
class Point{
int v1;
int v2;
int c;
Point(int v1,int v2,int c){
this.v1 = v1;
this.v2 = v2;
this.c = c;
}
}
class Node{
int v;
int c;
Node(int v,int c){
this.v = v;
this.c = c;
}
}
'알고리즘 > 백준' 카테고리의 다른 글
백준 11909 (배열 탈출) - java (0) | 2024.01.22 |
---|---|
백준 2533 사회망 서비스(SNS) - java (0) | 2024.01.18 |
백준 1167 (트리의 지름) - java (0) | 2024.01.15 |
백준 2450 (모양 정돈) - java (0) | 2024.01.15 |
백준 30894 (유령의 집) - java (0) | 2024.01.12 |
- Total
- Today
- Yesterday
- 백준
- 백준 #16973 #직사각형 탈출
- 백준 #5721 #사탕 줍기 대회 #java #자바
- 백준 #1987 #알파벳 #자바 #java
- 백준 #3980 #선발 명단
- 백준 #28140 #빨강~ 빨강~ 파랑! 파랑! 달콤한 솜사탕! #java #자바
- 백준 #2580 #스도쿠
- 백준 #4963 #섬의 개수
- 백준 #25603 #짱해커 이동식 #java #자바
- 백준 #13549 #숨바꼭질3
- 백준 #1325 #효율적인 해킹
- Java
- 백준 #치즈 #2638
- 자바 #JAVA
- 17218
- 백준 #25195 #yes or yes #java #자바
- 백준 #14863 #서울에서 경산까지 #java #자바
- 자바
- 백준 #1584 #게임 #java #자바
- 백준 #
- 백준 #인구 이동 #16234
- 백준 #17940 #주식 #자바 #java
- 백준 #다리 만들기 #2146
- 백준 #18405 #경쟁적 전염
- 백준 #12014 #주식 #자바 #java
- 백준 #1759 #암호 만들기
- 백준 #1727 #커플 만들기 #자바 #java
- 백준 #15686 #치킨 배달
- 17394
- 백준 #2636 #치즈
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |