알고리즘 관련/BOJ
BOJ)5542 JOI 국가의 행사
자손9319
2017. 9. 12. 02:35
문제: 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 |