Pagini recente » Cod sursa (job #3193442) | Cod sursa (job #739442) | Cod sursa (job #3173986) | Cod sursa (job #757150) | Cod sursa (job #1312787)
//Problem radiatie from Infoarena
#include <cassert>
#include <cmath>
#include <cstdint>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <queue>
#include <vector>
using namespace std;
ifstream fin("radiatie.in");
ofstream fout("radiatie.out");
const int INF = 1 << 30;
const int MAX_N = 15100;
const int MAX_LOG = 15;
#define mp make_pair
typedef pair<int, int> pii;
int N, M, K;
vector<int> graph[MAX_N];
vector<pair<pii, int>> edges;
vector<pii> tree[MAX_N];
vector<pii> queries;
int depth[MAX_N];
int anc[MAX_LOG][MAX_N];
int mxCost[MAX_LOG][MAX_N];
void apm() {
auto edgeComp = [](int e1, int e2) {
return edges[e1].second > edges[e2].second;
};
priority_queue<int, vector<int>, decltype(edgeComp)> heap(edgeComp);
vector<bool> visited(N + 1, false);
vector<bool> inApm(M, false);
auto get_free = [&visited](int e) {
int a = edges[e].first.first, b = edges[e].first.second;
return visited[a] ? b : a;
};
for (int i = 1, node = 1, next, edge; i < N; i += 1, node = next) {
visited[node] = true;
for_each(graph[node].begin(), graph[node].end(), [&heap](int e) {
heap.push(e);
});
do {
edge = heap.top();
next = get_free(edge);
heap.pop();
} while (visited[next]);
inApm[edge] = true;
}
for (int node = 1; node <= N; node += 1) {
for (auto e: graph[node]) {
if (inApm[e]) {
int other = edges[e].first.first + edges[e].first.second - node;
tree[node].push_back(mp(other, edges[e].second));
}
}
}
}
void dfs(int node) {
for (auto e: tree[node]) {
if (depth[e.first] == 0) {
depth[e.first] = depth[node] + 1;
anc[0][e.first] = node;
mxCost[0][e.first] = e.second;
dfs(e.first);
}
}
}
void find_ancestors() {
depth[1] = 1;
dfs(1);
for (int l = 1; l < MAX_LOG; l += 1) {
for (int i = 1; i <= N; i += 1) {
anc[l][i] = anc[l - 1][anc[l - 1][i]];
mxCost[l][i] = max(mxCost[l - 1][i], mxCost[l - 1][anc[l - 1][i]]);
}
}
}
int nth_anc(int node, int n) {
int result = 0;
for (int bit = MAX_LOG - 1; bit >= 0; bit -= 1) {
if (!((1 << bit) & n)) continue;
if ((1 << bit) == n) {
result = anc[bit][node];
} else {
node = anc[bit][node];
n ^= (1 << bit);
}
}
return result;
}
int lca(int a, int b) {
if (a == b) return a;
int da = depth[a], db = depth[b];
if (da > db) {
return lca(nth_anc(a, da - db), b);
} else if (da < db) {
return lca(a, nth_anc(b, db - da));
} else {
for (int bit = MAX_LOG - 1; bit >= 0; bit -= 1) {
if (anc[bit][a] != anc[bit][b]) {
a = anc[bit][a];
b = anc[bit][b];
}
}
return anc[0][a];
}
}
int find_greatest(int a, int b) {
if (a == b) return 0;
int ancestor = lca(a, b);
if (ancestor != a && ancestor != b) {
return max(find_greatest(a, ancestor), find_greatest(b, ancestor));
}
if (ancestor == a) swap(a, b);
int l = depth[a] - depth[ancestor];
int result = -INF;
for (int bit = MAX_LOG - 1; bit >= 0; bit -= 1) {
if ((1 << bit) & l) {
result = max(result, mxCost[bit][a]);
a = anc[bit][a];
l ^= (1 << bit);
}
}
return result;
}
void readin() {
fin >> N >> M >> K;
edges.resize(M);
for (int i = 0, a, b, c; i < M; i += 1) {
fin >> a >> b >> c;
edges[i] = mp(mp(a, b), c);
graph[a].push_back(i);
graph[b].push_back(i);
}
queries.resize(K);
for (int i = 0, a, b; i < K; i += 1) {
fin >> a >> b;
queries[i] = mp(a, b);
}
}
void solve() {
apm();
#ifdef DEBUG
for (int i = 1; i <= N; i += 1) {
fout << i << ": ";
for (auto j: tree[i]) {
fout << j.first << "[" << j.second << "] ";
}
fout << endl;
}
#endif
find_ancestors();
#ifdef DEBUG
for (int l = 0; l < 5; l += 1) {
for (int i = 1; i <= N; i += 1) {
fout << anc[l][i] << "[" << mxCost[l][i] << "] ";
}
fout << endl;
}
for (auto q: queries) {
fout << "lca(" << q.first << ", " << q.second << ") = " << lca(q.first, q.second) << endl;
}
#endif
for (auto q: queries) {
fout << find_greatest(q.first, q.second) << '\n';
}
}
int main() {
readin();
solve();
return 0;
}