Pagini recente » Cod sursa (job #2051827) | Cod sursa (job #506797) | Cod sursa (job #526668) | Cod sursa (job #2450343) | Cod sursa (job #2394501)
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
ifstream si("radiatie.in");
ofstream so("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;
si>>n>>m>>k;
vector<Edge> edges(m);
for(int i=0; i<m; ++i) {
si>>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;
si>>x>>y;
so<<mst.query(x, y)<<'\n';
}
return 0;
}