본문 바로가기

PS - 알고리즘

13209 - 검역소

 

 

step 1

더보기
더보기

검역소를 설치하는 것은 트리에서 간선을 끊는 것으로 생각할 수 있습니다. 즉 $K$개의 간선을 끊었을 때 각 트리에 있는 사람들 수의 합의 최대값을 최소로 하는 문제입니다. 문제를 살짝 바꿔서 "각 트리에 최대 $X$명의 사람이 있을 수 있다고 하면 적어도 몇 개의 다리를 끊어야 하는가"로 생각해 봅시다. $X$가 커질수록 끊어야 하는 다리의 수는 적어집니다. 따라서 이분 탐색으로 $X$값을 찾을 수 있습니다.

step 2

더보기
더보기

bridge[i] = i번째 정점을 루트로 생각했을 때 끊어야 하는 다리의 최소값

person[i] = bridge[i]를 최소로 만들었을 때 i번째 정점이 속한 트리에 있는 사람 수.

 

이 두 dp를 채운다고 생각합니다. 어떤 정점이 시작점이여도 답은 바뀌지 않으니 1번 정점을 루트로 생각합시다. dfs를 돌리면서 각 정점을 방문합니다. 그리고 정점을 빠져나올 때 dp값을 채워줍니다.

step 3

더보기
더보기

i의 자식 정점들을 $a_1, a_2, ..., a_n$이라 합시다. 편의상 person[$a_1$] $\le$ person[$a_2$] $\le ... \le$ person[$a_n$]이라 합시다. 저희는 person[i] $\le X$를 만족하면서 최대한 적은 다리를 끊어야 합니다. 그럼 i번 도시에 있는 사람에 person[$a_1$]부터 쭉 더해주다가 더이상 더하지 못할 때 이 이후에 있는 모든 다리를 끊어버리면 됩니다. 그럼 person[i]와 bridge[i]는 쉽게 구할 수 있습니다.

코드

더보기
더보기
#include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;
vector<long long int> v[200000];
long long int b[200000],ch[200000],bb[200000],cnt=0;
long long int dfs(long long int i,long long int xx) {
	long long int j;
	vector<long long int> vv;
	ch[i] = 1;
	for (j = 0; j < v[i].size(); j++) {
		if (ch[v[i][j]] == 0) { vv.push_back(dfs(v[i][j], xx)); }
	}
	long long int st = vv.size(),x=b[i];
	for (j = 1; j <= st; j++) bb[j] = vv[j-1];
	vv.clear();
	sort(bb + 1, bb + st + 1);
	for (j = 1; j <= st; j++) {
		if (x + bb[j] <= xx) x += bb[j]; else break;
	}
	cnt += st - j + 1;
	return x;
}
int main() {
	long long int n,tt,m,i,s,e,mi,max=-1;
	scanf("%lld", &tt);
	while (tt--) {
		scanf("%lld %lld", &n, &m);
		max = -1;
		for (i = 1; i <= n; i++) { scanf("%lld", &b[i]); if (max < b[i]) max = b[i]; }
		for (i = 1; i < n; i++) {
			long long int x, y;
			scanf("%lld %lld", &x, &y);
			v[x].push_back(y);
			v[y].push_back(x);
		}
		s = max;
		e = 3223300000000000000LL;
		while (s < e) {
			mi = (s + e) / 2;
			cnt = 0;
			for (i = 1; i <= n; i++)ch[i] = 0;
			dfs(1, mi);
			if (cnt <= m) e = mi; else s = mi + 1;
		}
		printf("%lld\n", s);
		for (i = 1; i <= n; i++) v[i].clear();
	}
	return 0;
}

'PS - 알고리즘' 카테고리의 다른 글

17242 - Kaka & Bebe  (0) 2024.06.13
17398 - 통신망 분할  (0) 2024.06.13
3043 - 장난감 탱크  (0) 2024.05.31
11873 - 최대 직사각형  (0) 2024.05.26
13537 - 수열과 쿼리 1  (0) 2024.05.26