문제: icpc.me/5542
쿼리에서 받는 두 도시간의 경로 중 경로에 포함 된 도시들의 축제하는 도시와의 떨어진 거리의 값들 중 최솟값이 최대가 되는 경로를 구하는 문제이다.
우선 다익스트라 알고리즘을 사용하여 각 정점들의 가중치(축제가 열리는 도시와의 최단거리)를 구해줄 수 있다.
이후 쿼리를 처리해주어야 하는데 disjoint set을 이용하여 쿼리를 처리해주려고 한다.
우선 각 쿼리 번호에 해당되는 양 끝 정점들에 쿼리 번호들을 저장해준 뒤
간선의 가중치가 큰 순서대로 간선을 정렬하여 간선을 보면서 정점을 dsu를 이용하여 병합해 줄것이다.
이 때 만약 두 정점이 같은 쿼리 번호를 가지고 있다면 해당 쿼리 번호의 답은 그 간선의 가중치가 될 것이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | #include <cstdio> #include <algorithm> #include <set> #include <vector> #include <cstring> #include <queue> using namespace std; int n, m, k, q, d[111111], res[111111]; vector<vector<pair<int, int>>> vt; set<int> st[111111]; int par[111111]; pair<int, pair<int, int>> edge[211111]; int find(int h) { return h == par[h] ? h : par[h] = find(par[h]); } void merge(int x, int y) { x = find(x); y = find(y); par[x] = y; } int main() { scanf("%d%d%d%d", &n, &m, &k, &q); vt.resize(n + 1); for (int i = 1; i <= n; i++) par[i] = i; for (int i = 0; i < m; i++) { int x, y, z; scanf("%d%d%d", &x, &y, &z); vt[x].push_back({ y,z }); vt[y].push_back({ x,z }); edge[i].second = { x,y }; } memset(d, -1, sizeof(d)); priority_queue<pair<int, int>> pq; for (int i = 0; i < k; i++) { int x; scanf("%d", &x); pq.push({ 0,x }); } while (pq.size()) { int here = pq.top().second; int cost = -pq.top().first; pq.pop(); if (d[here] != -1)continue; d[here] = cost; for (auto next : vt[here]) { if (d[next.first] == -1) pq.push({ -next.second - cost,next.first }); } } for (int i = 1; i <= q; i++) { int x, y; scanf("%d%d", &x, &y); st[x].insert(i); st[y].insert(i); } for (int i = 0; i < m; i++) edge[i].first = -min(d[edge[i].second.first], d[edge[i].second.second]); sort(edge, edge + m); for (int i = 0; i < m; i++) { int lo = find(edge[i].second.first); int hi = find(edge[i].second.second); if (lo == hi)continue; if (st[lo].size()>st[hi].size())swap(lo, hi); for (auto next : st[lo]) { if (st[hi].count(next)) { res[next] = -edge[i].first; st[hi].erase(next); } else st[hi].insert(next); } merge(lo, hi); } for (int i = 1; i <= q; i++) printf("%d\n", res[i]); return 0; } | cs |
'알고리즘 관련 > BOJ' 카테고리의 다른 글
BOJ)11443 짝수번째 피보나치 수의 합 (0) | 2017.10.14 |
---|---|
BOJ)5883 아이폰 9S (0) | 2017.10.13 |
BOJ)13330 유사 팰린드롬 (0) | 2017.09.08 |
BOJ)13352 석양이 진다... (1) | 2017.09.07 |
BOJ)5842 Partitioning the Farm (0) | 2017.09.07 |