Pagini recente » Cod sursa (job #1997658) | Cod sursa (job #95360) | Cod sursa (job #1848973) | Cod sursa (job #2599856) | Cod sursa (job #2393136)
#include <vector>
#include <fstream>
#include <algorithm>
using std::vector;
using std::pop_heap;
using std::make_heap;
std::ifstream fin("radiatie.in");
std::ofstream fout("radiatie.out");
inline int max(int x, int y) {
return x > y ? x : y;
}
inline void swap(int& x, int& y) {
int aux = x;
x = y;
y = aux;
}
int log2(int x) {
for (int i = 31; i >= 0; i--)
if (x & (1 << i))
return i;
return 0;
}
struct Edge {
int x, y;
int cost;
};
inline bool operator<(Edge x, Edge y) {
return x.cost > y.cost;
}
class Forest {
private:
vector<int> height;
vector<int> father;
public:
Forest(int n) {
height.resize(n + 1);
father.resize(n + 1);
}
int find(int x) {
int root = x;
while (father[root])
root = father[root];
int aux;
while (father[x]) {
aux = father[x];
father[x] = root;
x = aux;
}
return root;
}
void unite(int rootX, int rootY) {
if (height[rootX] < height[rootY])
father[rootX] = rootY;
else {
father[rootY] = rootX;
if (height[rootX] == height[rootY])
height[rootX]++;
}
}
};
class Tree {
private:
struct Node {
int node, cost;
Node(int node = 0, int cost = 0) {
this->node = node;
this->cost = cost;
}
};
int n;
vector<Node> father;
vector<vector<Node>> ad;
int height;
vector<int> level;
vector<vector<int>> anc;
vector<vector<int>> len;
int nthAnc(int node, int n) {
if (n > level[node])
return 0;
int k = node;
for (int i = 31; i >= 0; i--)
if (n & (1 << i))
k = anc[k][i];
return k;
}
void dfs(int node, int dad) {
for (Node nghb : ad[node])
if (nghb.node != dad) {
level[nghb.node] = level[node] + 1;
height = max(height, level[nghb.node]);
father[nghb.node] = Node(node, nghb.cost);
dfs(nghb.node, node);
}
}
public:
Tree(int n) {
this->n = n;
ad.resize(n + 1);
}
void addEdge(Edge edge) {
ad[edge.x].push_back(Node(edge.y, edge.cost));
ad[edge.y].push_back(Node(edge.x, edge.cost));
}
void dp() {
father.resize(n + 1);
level.resize(n + 1);
height = 0;
dfs(1, 0);
int log = log2(height);
anc = vector<vector<int>>(n + 1, vector<int>(log));
len = vector<vector<int>>(n + 1, vector<int>(log));
for (int i = 1; i <= n; i++) {
anc[i][0] = father[i].node;
len[i][0] = father[i].cost;
}
for (int j = 1; j <= log; j++)
for (int i = 1; i <= n; i++) {
anc[i][j] = anc[anc[i][j - 1]][j - 1];
len[i][j] = max(len[i][j - 1], len[anc[i][j - 1]][j - 1]);
}
}
int query(int x, int y) {
if (level[x] > level[y])
swap(x, y);
int sol = father[y].cost;
if (level[y] > level[x]) {
int z = level[y] - level[x];
for (int i = 31; i >= 0; i--)
if (z & (1 << i)) {
sol = max(sol, len[y][i]);
y = anc[y][i];
}
}
if (x == y)
return sol;
int lo = 0, hi = level[x] + 1;
while (hi - lo > 1) {
int md = (lo + hi) >> 1;
if (nthAnc(x, md) == nthAnc(y, md))
hi = md;
else
lo = md;
}
for (int i = 31; i >= 0; i--)
if (hi & (1 << i)) {
sol = max(sol, len[x][i]); x = anc[x][i];
sol = max(sol, len[y][i]); y = anc[y][i];
}
return sol;
}
};
Tree kruskal(int n, vector<Edge>& edges) {
Forest forest(n);
make_heap(edges.begin(), edges.end());
Tree mst(n);
for (int i = 1; i < n; ) {
Edge edge = edges[0];
pop_heap(edges.begin(), edges.end());
edges.pop_back();
int rootX = forest.find(edge.x);
int rootY = forest.find(edge.y);
if (rootX != rootY) {
i++;
mst.addEdge(edge);
forest.unite(rootX, rootY);
}
}
return mst;
}
int main() {
int n, m, k;
fin >> n >> m >> k;
vector<Edge> edges(m);
for (int i = 0; i < m; i++)
fin >> edges[i].x >> edges[i].y >> edges[i].cost;
Tree mst = kruskal(n, edges);
mst.dp();
for (int i = 0; i < k; i++) {
int x, y; fin >> x >> y;
fout << mst.query(x, y) << '\n';
}
fout.close();
return 0;
}