Pagini recente » Cod sursa (job #2359866) | Cod sursa (job #1208072) | Cod sursa (job #2702766) | Cod sursa (job #1258107) | Cod sursa (job #2906906)
#include <bits/stdc++.h>
using namespace std;
const int NMAX = 15e3;
const int MAX_LOG = 17;
const int ROOT = 1;
const int ERR = -1;
const int INF = 2e9;
int n, m, q;
struct define_edge {
int from, to, cost;
}; vector<define_edge> edges;
bool sort_cond ( define_edge first, define_edge second ) {
if ( first.cost == second.cost )
return first.to < second.to;
return first.cost < second.cost;
}
int father[1 + NMAX];
int get_sup ( int node ) {
if ( father[node] != node )
return father[node] = get_sup ( father[node] );
return node;
}
void join ( int first, int second ) {
int sup_first = get_sup ( first );
int sup_second = get_sup ( second );
father[sup_first] = sup_second;
}
void init_DSU () {
for ( int node = 1; node <= NMAX; node ++ )
father[node] = node;
}
vector<define_edge> answer;
void MSP () {
sort ( edges.begin (), edges.end (), sort_cond );
init_DSU ();
for ( auto edge : edges ) {
int first = edge.from, second = edge.to;
int cost = edge.cost;
if ( get_sup (first) != get_sup (second) ) {
join ( first, second );
answer.push_back ( { first, second, cost } );
}
}
}
bool visited[1 + NMAX]; int height[1 + NMAX];
vector<define_edge> graph[1 + NMAX];
define_edge parent[1 + MAX_LOG][1 + NMAX];
int lifting[1 + MAX_LOG][1 + NMAX];
void init_lifting () {
for ( int p = 0; p <= MAX_LOG; p ++ )
for ( int node = 1; node <= n; node ++ )
lifting[p][node] = INF;
}
void bfs ( int p, int start ) {
queue<int> bfs_q;
bfs_q.push ( start );
while ( !bfs_q.empty () ) {
int root = bfs_q.front (); bfs_q.pop ();
visited[root] = true;
if ( p == 0 )
lifting[p][root] = parent[0][root].cost;
else {
lifting[p][root] = max ( lifting[p - 1][root], lifting[p - 1][parent[p - 1][root].to] );
parent[p][root].to = parent[p - 1][parent[p - 1][root].to].to;
}
for ( auto obj : graph[root] )
if ( !visited[obj.to] )
bfs_q.push ( obj.to );
}
}
void dfs ( int root ) {
visited[root] = true;
for ( auto object : graph[root] ) {
int next_node = object.to;
int cost = object.cost;
if ( !visited[next_node] ) {
height[next_node] = height[root] + 1;
parent[0][next_node] = { ERR, root, cost };
dfs ( next_node );
}
}
}
void compute_tree () {
for ( auto edge : answer ) {
graph[edge.from].push_back ( { ERR, edge.to, edge.cost } );
graph[edge.to].push_back ( { ERR, edge.from, edge.cost } );
}
dfs ( ROOT ); init_lifting ();
for ( int p = 0; p <= MAX_LOG; p ++ ) {
for ( int node = 1; node <= n; node ++ )
visited[node] = false;
bfs ( p, ROOT );
}
}
int query ( int first, int second ) {
if ( height[first] < height[second] )
swap ( first, second );
int answer = -INF; height[parent[0][ROOT].to] = -INF;
for ( int p = MAX_LOG; p >= 0; p -- ) {
if ( height[parent[p][first].to] >= height[second] ) {
answer = max ( answer, lifting[p][first] );
first = parent[p][first].to;
}
}
for ( int p = MAX_LOG; p >= 0; p -- ) {
if ( parent[p][first].to != parent[p][second].to ) {
answer = max ( answer, lifting[p][first] );
answer = max ( answer, lifting[p][second] );
first = parent[p][first].to;
second = parent[p][second].to;
}
}
if ( first != second ) {
int p = 0;
while ( parent[p][first].to != parent[p][second].to )
p ++;
answer = max ( answer, lifting[p][first] );
}
return answer;
}
int main()
{
ifstream in ( "radiatie.in" );
ofstream out ( "radiatie.out" );
in >> n >> m >> q;
for ( int i = 1; i <= n; i ++ ) {
int a, b, cost; in >> a >> b >> cost;
edges.push_back ( { a, b, cost } );
}
MSP (); compute_tree ();
for ( int index = 1; index <= q; index ++ ) {
int a, b; in >> a >> b;
out << query ( a, b ) << "\n";
}
return 0;
}