https://www.acmicpc.net/problem/1647
제1647호:시분할계획
집의 수 N과 거리의 수 M은 첫 번째 줄에 주어집니다. N은 2 이상 100,000 이하의 정수이고, M은 1 이상 1,000,000 이하의 정수이다. 다음 라인에서 M 라인까지는 도로에 대한 정보가 3개의 정수 ABC로 주어진다.
www.acmicpc.net
문제를 해결하다
이 문제를 잘 분석해보면 큰 문제이고, 마을을 둘로 나누는 문제다. mst로 쉬운데 마을이 둘로 갈라지네요..? 조금만 생각해보면 가장 작은 Edge를 가진 Village들을 mst로 먼저 연결하고 그 중에서 가중치가 가장 큰 Edge를 빼면 쉽게 Village를 둘로 나눌 수 있음을 알 수 있습니다.
우리는 Prim 알고리즘을 사용했습니다.
#include <iostream>
#include <string>
#include <algorithm>
#include <limits.h>
#include <utility>
#include <vector>
#include <queue>
using namespace std;
struct cmp
{
bool operator()(const pair<int, int>& a, const pair<int, int>& b)
{
return a.second > b.second;
}
};
vector<pair<int, int> > node(100001);
int visit(100001);
priority_queue<pair<int, int>, vector<pair<int, int> >, cmp> pq;
int main()
{
std::cin.tie(nullptr);
std::cout.tie(nullptr);
std::ios_base::sync_with_stdio(false);
int N, M;
cin >> N >> M;
for (int i = 0; i < M; ++i)
{
int A, B, C;
cin >> A >> B >> C;
node(A).push_back({ B, C });
node(B).push_back({ A, C });
}
int max_wei = 0;
int sum = 0;
int cnt = 0;
pq.push({ 1, 0 });
while (!pq.empty())
{
pair<int, int> cur = pq.top();
pq.pop();
if (visit(cur.first))
continue;
max_wei = max(max_wei, cur.second);
sum += cur.second;
visit(cur.first) = 1;
++cnt;
if (cnt == N)
break;
for (int i = 0; i < node(cur.first).size(); ++i)
pq.push(node(cur.first)(i));
}
cout << sum - max_wei;
return 0;
}
메모리: 56604KB, 시간: 792ms