문제링크 : https://www.acmicpc.net/problem/1647
1647번: 도시 분할 계획
첫째 줄에 집의 개수 N, 길의 개수 M이 주어진다. N은 2이상 100,000이하인 정수이고, M은 1이상 1,000,000이하인 정수이다. 그 다음 줄부터 M줄에 걸쳐 길의 정보가 A B C 세 개의 정수로 주어지는데 A번
www.acmicpc.net
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int MAX = 987654321;
struct p
{
int u, v, weight;
bool operator<(p const &e) //가중치가 작은 것부터
{
return weight < e.weight;
}
};
int N, M, result;
int parent[100001];
vector<p>v;
int find_root(int x) //부모찾기
{
if(x == parent[x]) return x;
return parent[x] = find_root(parent[x]);
}
bool check(int a, int b) //이어졌는가?
{
a=find_root(a);
b=find_root(b);
if(a==b) return 1;
return 0;
}
void Union(int a, int b) //병합
{
a=find_root(a);
b=find_root(b);
parent[b]=a;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cin >> N >> M;
for(int i=0; i<M; i++)
{
int a, b, c;
cin >> a >> b >> c;
v.push_back({a, b, c});
}
sort(v.begin(), v.end());
for(int i=1; i<=N; i++) //부모 초기화
{
parent[i] = i;
}
int maxV = 0;
for(int i=0; i<M; i++)
{
if (!check(v[i].u, v[i].v)) //부모가 다르면 (이어져있지 않다면)
{
maxV = max(maxV, v[i].weight); //가장 유지비가 높은 가중치 저장 (분리예정)
Union(v[i].u, v[i].v); //간선 이어주기
result += v[i].weight; //가중치 합산
}
}
cout << result - maxV;
return 0;
}
백준 1197번과 유사하게 크루스컬이나 프림 알고리즘으로 풀 수 있는 최소 스패닝 트리 (MST) 문제이다.
참고 : https://blob-thinking.tistory.com/248
[백준 1197번] 최소 스패닝 트리 (C++)
문제링크 : https://www.acmicpc.net/problem/1197 1197번: 최소 스패닝 트리 첫째 줄에 정점의 개수 V(1 ≤ V ≤ 10,000)와 간선의 개수 E(1 ≤ E ≤ 100,000)가 주어진다. 다음 E개의 줄에는 각 간선에 대한 정보를
blob-thinking.tistory.com
해당 문제와 다른 점은 만든 최소 스패닝 트리를 2개로 분리해야 하는 점이다.
2개로 분리할때 기존에 이어졌던 길은 필요가 없고, 유지비의 합을 최소로 하고자한다.
따라서 기존 최소 스패닝 트리에서 가장 가중치가 큰 간선을 제거하여 마을을 2개로 분리시켜 주면된다.
이를 위해 가장 유지비가 높은 가중치를 따로 저장하고, 출력할때 기존 MST의 가중치에서 해당 가중치를 빼서 출력을 해주었다.
'백준 > 골드' 카테고리의 다른 글
[백준 2239번] 스도쿠 (C++) (0) | 2023.09.10 |
---|---|
[백준 17404번] RGB거리 2 (C++) (0) | 2023.09.09 |
[백준 14002번] 가장 긴 증가하는 부분 수열 4 (C++) (0) | 2023.09.07 |
[백준 1351번] 무한 수열 (C++) (0) | 2023.09.04 |
[백준 1229번] 육각수 (C++) (0) | 2023.09.02 |