Pagini recente » Cod sursa (job #1654529) | Cod sursa (job #3350202) | Cod sursa (job #1400916) | Cod sursa (job #1965059) | Cod sursa (job #3340514)
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
#define in fin
#define out fout
ifstream fin("radiatie.in");
ofstream fout("radiatie.out");
typedef pair<int, int> pii;
const int MAXN = 15e3;
const int MAXM = 3e4;
const int MAXLOG = 15;
struct muchie {
int cost;
int x, y;
};
// 1. determinarea APM
// 2. aleg o radacina random si fac LCA cu RMQ
// 3. am ceva matrice m[i][j] = costul maxim dintre nodul i si stramosul lui, 2^j sa fac toate queryurile O(1)
int n, m, qrs, x, y, z, idx_apm, ek;
int repr[MAXN+1], tata[MAXN+1], level[MAXN+1];
int euler[2*MAXN+1], nivele[2*MAXN+1];
int first_app[MAXN+1]; // prima aparitie a nodului i in reprezentarea euler
bool viz[MAXN+1];
int lg2[MAXN+1];
int rmq[MAXLOG][2*MAXN+1];
vector<pii> grafAPM[MAXN+1];
muchie muchii[MAXM+1], APM[MAXN+1];
map<pii, int> muchie_cost;
int radacina(int nod) {
if (repr[nod] == nod)
return nod;
return repr[nod] = radacina(repr[nod]);
}
void combine(int r1, int r2) {
if (r1 < r2)
repr[r2] = repr[r1];
else
repr[r1] = repr[r2];
}
void kruskal() {
for (int i = 1; i <= n; i++)
repr[i] = i;
sort(muchii + 1, muchii + m + 1, [](muchie a, muchie b){
return a.cost < b.cost;
});
for (int i = 1; i <= m; i++) {
int x = muchii[i].x, y = muchii[i].y;
int cost = muchii[i].cost;
int r1 = radacina(x);
int r2 = radacina(y);
if (r1 != r2) {
APM[++idx_apm] = muchii[i];
combine(r1, r2);
}
}
}
void build_grafAPM() {
for (int i = 1; i < n; i++) {
int x = APM[i].x, y = APM[i].y;
int z = APM[i].cost;
grafAPM[x].push_back({y, z});
grafAPM[y].push_back({x, z});
}
}
void dfs_euler(int nod, int nivel, int padre) {
++ek;
nivele[ek] = nivel;
euler[ek] = nod;
level[nod] = nivel;
viz[nod] = true;
first_app[nod] = ek;
tata[nod] = padre;
for (auto e: grafAPM[nod])
if (!viz[e.first]) {
dfs_euler(e.first, nivel + 1, nod);
++ek;
nivele[ek] = nivel;
euler[ek] = nod;
}
}
void build_RMQ() {
lg2[0] = lg2[1] = 0;
for (int i = 2; i <= MAXN; i++)
lg2[i] = lg2[i / 2] + 1;
for (int i = 1; i <= ek; i++)
rmq[0][i] = nivele[i];
for (int i = 1; i <= lg2[ek]; i++)
for (int j = 1; j <= ek - (1 << i) + 1; j++) {
rmq[i][j] = min(
rmq[i - 1][j],
rmq[i - 1][j + (1 << (i - 1))]
);
}
}
int LCA(int nod1, int nod2) {
int st = min( first_app[nod1], first_app[nod2] );
int dr = max( first_app[nod1], first_app[nod2] );
int lgk = lg2[dr - st];
int minRMQ = min(
rmq[lgk][st],
rmq[lgk][dr - (1 << lgk) + 1]
);
return first_app[ minRMQ ];
}
int mat[MAXN+1][MAXLOG+1];
void build_mat() {
for (int i = 1; i <= n; i++) {
int nod = i, ancestor = tata[nod];
int j = 1;
while (tata[nod]) {
mat[i][j] = max( muchie_cost[{nod, tata[nod]}], mat[i][j-1] );
nod = tata[nod];
j++;
}
}
}
int main() {
in >> n >> m >> qrs;
for (int i = 1; i <= m; i++) {
in >> x >> y >> z;
muchii[i] = {z, x, y};
muchie_cost[{x, y}] = muchie_cost[{y, x}] = z;
}
// determinam APM cu kruskal DSU
idx_apm = 0;
kruskal();
// construim reprezentarea euler
ek = 0;
build_grafAPM();
dfs_euler(1, 1, 0); // luam arbitrar radacina APM-ului 1
// construim simultan si vectorul de tati
// construim RMQ
build_RMQ();
// construim matricea drumurilor maxime
// mat[i][j] = valoarea maxima a drumului de la nodul i la stramosul al j-lea (j = 1 fiind tatal lui i)
build_mat();
// raspundem query-urilor
for (int i = 1; i <= qrs; i++) {
in >> x >> y;
int lca = LCA(x, y);
int dist_x_lca = abs(level[x] - level[lca]);
int dist_y_lca = abs(level[y] - level[lca]);
int maxroad_x_lca = mat[x][dist_x_lca];
int maxroad_y_lca = mat[y][dist_y_lca];
out << max(maxroad_x_lca, maxroad_y_lca) << '\n';
}
return 0;
}