Pagini recente » Cod sursa (job #1262528) | Cod sursa (job #1938842) | Cod sursa (job #479810) | Cod sursa (job #717536) | Cod sursa (job #2877371)
#include <fstream>
#include <algorithm>
#include <vector>
using namespace std;
ifstream fin("radiatie.in");
ofstream fout("radiatie.out");
#define DIM 15000
#define INF (1LL << 30)
typedef pair <int, int> PII;
int n, m, q, k;
bool sel[DIM + 1]; //ce noduri parcurg in dfs;
int sef[DIM + 1];
int Euler[4 * DIM + 1], nivel[4 * DIM + 1], ap[4 * DIM + 1]; //pentru lca;
int lg[2 * DIM + 1];
int Rmq[20][8 * DIM + 1];
PII t[DIM + 1]; //retin tatal unui nod si costul;
vector <PII> Apm[DIM + 1];
struct nanu {
int x, y, c;
}M[2 * DIM + 1];
static inline bool cmp(nanu a, nanu b) {
return (a.c < b.c);
}
static inline int radacina(int nod) {
if(sef[nod] == nod)
return nod;
return sef[nod] = radacina(sef[nod]);
}
static inline void Union(int x, int y) {
if(x < y)
sef[y] = x;
else sef[x] = y;
}
static inline void Kruskal() {
for(int i = 1; i <= n; i++)
sef[i] = i; //fiecare element reprezinta o comp. conexa;
sort(M + 1, M + m + 1, cmp); //sortez muchiile crescator dupa cost;
for(int i = 1; i <= m; i++) {
int rad1 = radacina(M[i].x);
int rad2 = radacina(M[i].y);
if(rad1 != rad2) {
Union(rad1, rad2);
Apm[M[i].x].push_back({M[i].y, M[i].c});
Apm[M[i].y].push_back({M[i].x, M[i].c});
}
}
}
static inline void dfs(int nod, int lvl, int tata, int cost) {
sel[nod] = 1;
t[nod] = {tata, cost};
Euler[++k] = nod;
nivel[k] = lvl;
ap[nod] = k; //prima aparitie pe care se afla nodul nod;
for(auto e : Apm[nod])
if(!sel[e.first] && t[nod].first != e.first) {
dfs(e.first, lvl + 1, nod, e.second);
Euler[++k] = nod;
nivel[k] = lvl;
}
}
static inline void RMQ() {
for(int i = 2; i <= k; i++)
lg[i] = lg[i / 2] + 1;
for(int i = 1; i <= k; i++)
Rmq[0][i] = i; //indicii;
for(int i = 1; (1 << i) < k; i++)
for(int j = 1; j <= k - (1 << i); j++) {
int l = 1 << (i - 1);
if(nivel[Rmq[i - 1][j]] < nivel[Rmq[i - 1][j + l]])
Rmq[i][j] = Rmq[i - 1][j];
else Rmq[i][j] = Rmq[i - 1][j + l];
}
}
static inline int lca(int x, int y) {
int a = ap[x], b = ap[y];
if(a > b)
swap(a, b);
int dif = b - a + 1;
int l = lg[dif];
int q = dif - (1 << l);
int nod;
if(nivel[Rmq[l][a]] < nivel[Rmq[l][a + q]])
nod = Rmq[l][a];
else nod = Rmq[l][a + q];
return Euler[nod]; //nodul de pe acel nivel;
}
static inline int Path_to_lca(int nod, int stramos) {
int maxim = 0;
while(nod != stramos) {
maxim = max(maxim, t[nod].second);
nod = t[nod].first;
}
return maxim;
}
int main() {
fin.tie(0);
fout.tie(0);
fin >> n >> m >> q;
for(int i = 1; i <= m; i++)
fin >> M[i].x >> M[i].y >> M[i].c; //retin muchiile;
//Retin arborele de cost minim pentru a avea cele mai mici canale intre puncte;
Kruskal();
//Voi folosi lca pentru complexitate;
//Un bfs din x in y inseamna O(q * (N + M));
k = 0; //numarul de noduri din parcurgerea euleriana;
nivel[0] = INF; //santinela;
dfs(1, 0, 0, 0);
RMQ();
int x, y;
for(int i = 1; i <= q; i++) {
fin >> x >> y;
int stramos = lca(x, y);
int drum1 = Path_to_lca(x, stramos);
int drum2 = Path_to_lca(y, stramos);
fout << max(drum1, drum2) << '\n';
}
return 0;
}