Cod sursa(job #3278722)

Utilizator BledeaAlexBledea Alexandru BledeaAlex Data 20 februarie 2025 17:02:38
Problema Radiatie Scor 40
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.75 kb
#include <bits/stdc++.h>

using namespace std;

const int N_MAX = 15005, LOG_N = 13, M_MAX = 30005, K_MAX = 15005;
int N, M, K, logN;

int timer;
int tin[2 * N_MAX], tout[2 * N_MAX];
int T[N_MAX][LOG_N];
int Max[N_MAX][LOG_N];

bitset<N_MAX> visited;

struct FixedEdge
{
    int v1, v2, c;

    inline bool operator< (const FixedEdge& rhs) const
    {
        return c < rhs.c;
    }
};

struct Edge
{
    int v, c;

    Edge(int _v, int _c) :
        v(_v), c(_c) { }
};

FixedEdge Edges[M_MAX];
vector<Edge> G[N_MAX];

struct DisjointSetUnion
{
    int T[N_MAX];
    int Size[N_MAX];
    int N;

    inline void MakeSet(int v)
    {
        T[v] = v;
        Size[v] = 1;
    }

    int FindSet(int v)
    {
        if(T[v] != v)
            T[v] = FindSet(T[v]);
        return T[v];
    }

    bool AreDisjoint(int a, int b)
    {
        return FindSet(a) != FindSet(b);
    }

    void Union(int a, int b)
    {
        a = FindSet(a);
        b = FindSet(b);

        if(a == b)
            return;

        if(Size[a] < Size[b])
            swap(a, b);

        T[b] = a;
        Size[a] += Size[b];
    }

    void Build(int N)
    {
        this->N = N;

        for(int i = 1; i <= N; i++)
            MakeSet(i);
    }
} dsu;

void SetInput(string name)
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    (void)!freopen((name + ".in").c_str(), "r", stdin);
    (void)!freopen((name + ".out").c_str(), "w", stdout);
}

void ReadInput()
{
    cin >> N >> M >> K;
    for(int i = 0; i < M; i++)
        cin >> Edges[i].v1 >> Edges[i].v2 >> Edges[i].c;
}

void Kruskal()
{
    sort(Edges, Edges + M);

    for(int i = 0; i < M; i++)
    {
        auto [v1, v2, c] = Edges[i];
        if(dsu.AreDisjoint(v1, v2))
        {
            dsu.Union(v1, v2);
            G[v1].emplace_back(v2, c);
            G[v2].emplace_back(v1, c);
        }
    }
}

void DFS(int v, int p)
{
    visited[v] = 1;
    tin[v] = ++timer;
    T[v][0] = p;

    for(int i = 1; i <= logN; i++)
    {
        T[v][i] = T[T[v][i-1]][i-1];
        Max[v][i] = max(Max[v][i-1], Max[T[v][i-1]][i-1]);
    }

    for(auto& [u, cost] : G[v])
        if(u != p)
        {
            Max[u][0] = cost;
            DFS(u, v);
        }

    tout[v] = ++timer;
}

inline bool IsAncestor(int& u, int& v)
{
    return tin[u] <= tin[v] && tout[u] >= tout[v];
}

int LCA(int u, int v)
{
    if(IsAncestor(u, v))
        return u;

    if(IsAncestor(v, u))
        return v;

    for(int i = logN; i >= 0; i--)
        if(not IsAncestor(T[u][i], v))
            u = T[u][i];

    return T[u][0];
}

void BuildLCA()
{
    timer = 0;
    logN = ceil(log2(N));

    for(int i = 1; i <= N; i++)
        if(not visited[i])
        {
            Max[i][0] = 0;
            DFS(i, i);
        }
}

int FindMaxInPath(int v, int p)
{
    if(v == p)
        return 0;

    if(not IsAncestor(p, v))
        return 0;

    int ans = 0;
    for(int i = logN; i >= 0; i--)
        if(not IsAncestor(T[v][i], p))
        {
            ans = max(ans, Max[v][i]);
            v = T[v][i];
        }

    ans = max(ans, Max[v][0]);

    return ans;
}

void AnswerQueries()
{
    for(int i = 0, u, v, lca, ans; i < K; i++)
    {
        cin >> u >> v;

        if(dsu.AreDisjoint(u, v))
        {
            cout << "0\n";
            continue;
        }

        lca = LCA(u, v);

        ans = FindMaxInPath(u, lca);
        ans = max(ans, FindMaxInPath(v, lca));

        cout << ans << '\n';
    }
}

int main()
{
    SetInput("radiatie");

    ReadInput();
    dsu.Build(N);
    Kruskal();
    BuildLCA();
    AnswerQueries();

    return 0;
}