[BOJ 13209] 검역소

2023. 4. 22. 13:31Baekjoon

728x90

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

 

13209번: 검역소

3번 도시와 5번 도시를 잇는 도로와 4번 도시와 3번 도시를 잇는 도로에 검역소를 설치하면 치료제를 11 인분만 비축해도 된다. 1번 도시에 전염병이 발생할 경우 1번 도시와 3번 도시의 10명의 사

www.acmicpc.net

 

- 문제 요약

 

한 나라에는 N 개의 도시들이 있고, 두 도시 사이를 연결하는 길이 N − 1개 있다.

어느 두 도시도 오직 하나의 경로로만 서로 통행할 수 있게 되어 있고, 이곳에는 몇 년에 한 번씩 큰 전염병이 돈다.

정부에서는 이 문제를 해결하기 위해 N −1 개의 길들 중 K 개의 길에 검역소를 운영하려고 한다.

또한, 어떤 사람이 전염병에 감염될 경우를 대비하여 치료제를 비축해 두려고 한다.

어떤 한 사람이 전염병에 감염될 때에도 전염병에 걸릴 수 있는 모든 사람들이 치료제를 하나씩 받을 수 있게 하기 위해 비축해야 할 치료제의 최소 개수를 구하여라.

 

 

- 알고리즘 정리

 

필요한 치료제의 최소 개수를 구하는 문제입니다. 

이분 탐색을 하면서 dfs로 각 정점에서 탐색을 진행해줍니다. 

탐색을 하면서 각 컴포넌트 가중치의 합이 mid 값(이분탐색)보다 작아지도록 나눠주고, 제거한 간선의 개수가 K보다 작은지 확인해 주면 문제를 해결할 수 있습니다.

 

 

- 코드 작성

 

#include<bits/stdc++.h>
using namespace std;

#define MAX 100001
typedef long long ll;
int t,n,k;
ll arr[MAX],mx,cnt,l,r;
vector<int>v[MAX];

ll dfs(int x,int w=-1){
	priority_queue<ll>pq;
	ll now=arr[x];
	for(auto i:v[x]){
		if(i!=w){
			ll tmp=dfs(i,x);
			now+=tmp;
			pq.push(tmp);
		}
	}
	while(pq.size()&&now>mx){
		now-=pq.top();
		pq.pop();
		cnt++;
	}
	return now;
}

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cin>>t;
	while(t--){
		ll sum=0;
		cin>>n>>k;
		for(int i=1;i<=n;i++){
			cin>>arr[i];
			sum+=arr[i];
			v[i].clear();
		}
		for(int i=1;i<n;i++){
			ll s,e;
			cin>>s>>e;
			v[s].push_back(e);
			v[e].push_back(s);
		}
		ll l=*max_element(arr+1,arr+n+1);
		r=sum;
		while(l<r){
	        ll mid=(l+r)/2;
	        cnt=0;
	        mx=mid;
	        dfs(1);
	        if(cnt<=k){
	        	r=mid;
			}
			else{
				l=mid+1;
			}
		}
		cout<<r<<'\n';
	}
}

코드 제출 결과

 

728x90

'Baekjoon' 카테고리의 다른 글

[BOJ 9497] 피라미드 수열  (1) 2023.04.23
[BOJ 11402] 이항 계수 4  (0) 2023.04.22
[BOJ 19590] 비드맨  (0) 2023.04.21
[BOJ 17611] 직각다각형  (1) 2023.04.21
[BOJ 10937] 두부 모판 자르기  (1) 2023.04.20