題解【洛谷P1967】[NOIP2013]貨車運輸

題面c++

題解

注意到有一些限重很低的邊不會被走到。spa

因而考慮建一棵最大生成樹,在生成樹上尋找答案。code

\(f[i][j]\)表示\(i\)\(2^j\)級祖先,\(w[i][j]\)表示\(i\)\(2^j\)級祖先的最大載重。get

那麼咱們在倍增尋找\(\text{LCA}\)時更新答案便可。it

代碼

#include <bits/stdc++.h>
#define itn int
#define gI gi

using namespace std;

inline int gi()
{
    int f = 1, x = 0; char c = getchar();
    while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
    while (c >= '0' && c <= '9') x = x * 10 + (c ^ 48), c = getchar();
    return f * x;
}

const int maxn = 100003;

int q, n, m, tot, head[maxn], ver[maxn], edge[maxn], nxt[maxn], fa[maxn][23];
int f[maxn], w[maxn][23], vis[maxn], dep[maxn];
struct Node
{
    int u, v, w;
} e[maxn];

inline bool cmp(Node x, Node y) {return x.w > y.w;}

int getf(int u)
{
    if (f[u] == u) return u;
    return f[u] = getf(f[u]);
}

inline void add(int u, int v, int w)
{
    ver[++tot] = v, nxt[tot] = head[u], edge[tot] = w, head[u] = tot;
}

inline void get_MST()
{
    for (int i = 1; i <= n; i+=1) f[i] = i;
    for (int i = 1; i <= m; i+=1)
    {
        int U = getf(e[i].u), V = getf(e[i].v);
        if (U != V)
        {
            f[U] = V;
            add(e[i].u, e[i].v, e[i].w);
            add(e[i].v, e[i].u, e[i].w);
        }
    }
}

void dfs(int u)
{
    vis[u] = 1;
    for (int i = head[u]; i; i = nxt[i])
    {
        int v = ver[i], ww = edge[i];
        if (vis[v]) continue;
        dep[v] = dep[u] + 1;
        fa[v][0] = u;
        w[v][0] = ww;
        dfs(v);
    }
}

inline int getans(int u, int v)
{
    if (dep[u] > dep[v]) swap(u, v);
    int uu = 0x3f3f3f3f;
    for (int i = 20; i >= 0; i-=1)
    {
        if (dep[fa[v][i]] >= dep[u]) uu = min(uu, w[v][i]),  v = fa[v][i];
    }
    if (u == v) return uu;
    for (int i = 20; i >= 0; i-=1)
    {
        if (fa[u][i] != fa[v][i])
        {
            uu = min(uu, min(w[u][i], w[v][i]));
            u = fa[u][i], v = fa[v][i];
        }
    }
    uu = min(uu, min(w[u][0], w[v][0]));
    return uu;
}

int main()
{
    //freopen(".in", "r", stdin);
    //freopen(".out", "w", stdout);
    n = gi(), m = gi();
    for (int i = 1; i <= m; i+=1)
    {
        int u = gi(), v = gi(), w = gi();
        e[i].u = u, e[i].v = v, e[i].w = w;
    }
    sort(e + 1, e + 1 + m, cmp);
    get_MST();
    for (int i = 1; i <= n; i+=1)
    {
        if (!vis[i])
        {
            dep[i] = 1;
            dfs(i);
            fa[i][0] = i;
            w[i][0] = 0x3f3f3f3f;
        }
    }
    for (int i = 1; i <= 20; i+=1)
        for (int j = 1; j <= n; j+=1)
            fa[j][i] = fa[fa[j][i - 1]][i - 1],
                w[j][i] = min(w[j][i - 1], w[fa[j][i - 1]][i - 1]);
    q = gi();
    while (q--)
    {
        int u = gi(), v = gi();
        if (getf(u) != getf(v)) {puts("-1"); continue;}
        printf("%d\n", getans(u, v));
    }
    return 0;
}
相關文章
相關標籤/搜索