메모리: 53512 KB, 시간: 528 ms
자료 구조, 분리 집합, 다이나믹 프로그래밍, 그래프 이론, 그래프 탐색, 배낭 문제
2025년 1월 19일 19:55:26
Trick or Treat!!
10월 31일 할로윈의 밤에는 거리의 여기저기서 아이들이 친구들과 모여 사탕을 받기 위해 돌아다닌다. 올해 할로윈에도 어김없이 많은 아이가 할로윈을 즐겼지만 단 한 사람, 일찍부터 잠에 빠진 스브러스는 할로윈 밤을 즐길 수가 없었다. 뒤늦게 일어나 사탕을 얻기 위해 혼자 돌아다녀 보지만 이미 사탕은 바닥나 하나도 얻을 수 없었다.
단단히 화가 난 스브러스는 거리를 돌아다니며 다른 아이들의 사탕을 빼앗기로 마음을 먹는다. 다른 아이들보다 몸집이 큰 스브러스에게 사탕을 빼앗는 건 어렵지 않다. 또한, 스브러스는 매우 공평한 사람이기 때문에 한 아이의 사탕을 뺏으면 그 아이 친구들의 사탕도 모조리 뺏어버린다. (친구의 친구는 친구다?!)
사탕을 빼앗긴 아이들은 거리에 주저앉아 울고 명 이상의 아이들이 울기 시작하면 울음소리가 공명하여 온 집의 어른들이 거리로 나온다. 스브러스가 어른들에게 들키지 않고 최대로 뺏을 수 있는 사탕의 양을 구하여라.
스브러스는 혼자 모든 집을 돌아다녔기 때문에 다른 아이들이 받은 사탕의 양을 모두 알고 있다. 또한, 모든 아이는 스브러스를 피해 갈 수 없다.
첫째 줄에 정수 , , 가 주어진다.
은 거리에 있는 아이들의 수, 은 아이들의 친구 관계 수, 는 울음소리가 공명하기 위한 최소 아이의 수이다. (, , )
둘째 줄에는 아이들이 받은 사탕의 수를 나타내는 정수 이 주어진다. ()
셋째 줄부터 개 줄에 갈쳐 각각의 줄에 정수 , 가 주어진다. 이는 와 가 친구임을 의미한다. 같은 친구 관계가 두 번 주어지는 경우는 없다. (, )
스브러스가 어른들에게 들키지 않고 아이들로부터 뺏을 수 있는 최대 사탕의 수를 출력한다.
/**
* Author: yngbao97, Yuk Yejin
* Problem: 할로윈의 양아치_20303
* Date: 2025.01.19
*/
import java.util.*;
import java.lang.*;
import java.io.*;
public class Main {
static BufferedReader br;
static BufferedWriter bw;
static StringTokenizer st;
static Group[] kids;
static int[] p;
public static void main(String[] args) throws Exception {
br = new BufferedReader(new InputStreamReader(System.in));
bw = new BufferedWriter(new OutputStreamWriter(System.out));
String[] input = br.readLine().split(" ");
int n = Integer.parseInt(input[0]);
int m = Integer.parseInt(input[1]);
int k = Integer.parseInt(input[2]);
kids = new Group[n+1];
p = new int[n+1];
Set<Group> realS = new HashSet<>();
st = new StringTokenizer(br.readLine(), " ");
for (int i = 1; i <= n; i++) {
kids[i] = new Group(1, Integer.parseInt(st.nextToken()));
realS.add(kids[i]);
p[i] = i;
}
for (int i = 0; i < m; i++) {
String[] rel = br.readLine().split(" ");
int a = Integer.parseInt(rel[0]);
int b = Integer.parseInt(rel[1]);
int bossA = findSet(a);
int bossB = findSet(b);
if (bossA != bossB) {
realS.remove(kids[bossB]);
kids[bossA].children += kids[bossB].children;
kids[bossA].candy += kids[bossB].candy;
p[bossB] = bossA;
}
}
List<Group> groups = new ArrayList<>(realS);
Collections.sort(groups);
int[] dp = new int[k];
for (Group g : groups) {
for (int i = k-1; i > 0; i--) {
if (i >= g.children) dp[i] = Math.max(dp[i], dp[i - g.children] + g.candy);
}
}
bw.write(String.valueOf(dp[k-1]));
bw.flush();
bw.close();
br.close();
}
private static int findSet(int x) {
if (p[x] == x) return x;
return p[x] = findSet(p[x]);
}
}
class Group implements Comparable<Group> {
int children;
int candy;
Group(int children, int candy) {
this.children = children;
this.candy = candy;
}
@Override
public int compareTo(Group o) {
return Integer.compare(this.children, o.children);
}
@Override
public String toString() {
return children + "명 " + candy + "개";
}
}