알고리즘

BOJ 1647: 도시 분할 계획

minbear 2023. 7. 26. 16:11

#BOJ 1647: 도시 분할 계획

 

1647번: 도시 분할 계획

첫째 줄에 집의 개수 N, 길의 개수 M이 주어진다. N은 2이상 100,000이하인 정수이고, M은 1이상 1,000,000이하인 정수이다. 그 다음 줄부터 M줄에 걸쳐 길의 정보가 A B C 세 개의 정수로 주어지는데 A번

www.acmicpc.net

#풀이

문제에서 임의의 두집 사이에 경로가 항상 존재한다라는 조건이 있고 유지비의 합을 최소를 출력해야 한다.

이것을 보고 최소 신장 트리 로 풀 수 있다.

 

하지만 문제는 마을을 2개로 쪼개야 하는 문제이다.

 

간단하게 생각하면 최소로 유지를 해야 하니 최소 신장 트리에서 가장 큰 가중치를 갖고 있는 간선을 빼버리면

2개의 마을이 생겨 난다는 걸 알 수 있다.

 

최소 신장 트리의 최소 가중치를 구한 다음 최소 신장 트리에 있는 가장 큰 가중치를 빼면 된다.

#코드

#include<bits/stdc++.h>

using namespace std;
int n, m;
vector<int> p(100001, -1);
vector<tuple<int,int,int>> road;
int find(int x){
	if(p[x] <0)
	return x;
	return p[x] = find(p[x]);
}
bool is_diff(int a, int b){
	int u, v;
	u = find(a);
	v = find(b);
	if(u==v) return 0;
	if(u<=v) p[v] = u;
	else p[u] =v;
	return 1;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >>n >> m;
	
	for(int i = 0; i <m; i++){
		int w, a, b;
		cin >> a >> b >> w;
		road.push_back({w,a,b});
	}
	sort(road.begin(), road.end());
	
	long long ans = 0;
	int cnt = 0;
	int max = 0;
	for(auto nxt : road){
		int w, a, b;
		tie(w,a,b) = nxt;
		if(!is_diff(a,b)) continue;
		ans += w;
		max = max < w ? w : max;
		cnt++;
		if(cnt== n-1) break;
	
	}
	cout << ans - max<<'\n';
	return 0;
}