• 洛谷 P1967 货车运输


    题意简述

    给定一张图,求两点最短路径上的点的值的最小值

    题解思路

    先进行最大生成树,再倍增求lca

    代码

    #include <cstdio>
    #include <algorithm>
    struct Edge
    {
        int u, v, w;
    }e[51000];
    int n, m, q, u, v, w, xx, yy, cnt;
    int fa[11000];
    int h[21000], to[21000], nxt[21000], val[21000];
    int lg[21000], dep[21000], f[21000][20][2];
    inline bool cmp(const Edge& x, const Edge& y) {return x.w > y.w; }
    int find(const int& x) {return x ^ fa[x] ? fa[x] = find(fa[x]) : x; }
    inline void add_edge(const int& u, const int& v, const int& w)
    {
        to[++cnt] = v;
        val[cnt] = w;
        nxt[cnt] = h[u];
        h[u] = cnt;
    }
    void dfs(const int& x)
    {
        for (register int i = 0; f[x][i][0]; ++i)
        {
            f[x][i + 1][0] = f[f[x][i][0]][i][0];
            f[x][i + 1][1] = std::min(f[x][i][1], f[f[x][i][0]][i][1]);
        }
        for (register int i = h[x]; i; i = nxt[i])
            if (to[i] ^ f[x][0][0])
            {
                dep[to[i]] = dep[x] + 1;
                f[to[i]][0][0] = x;
                f[to[i]][0][1] = val[i];
                dfs(to[i]);
            }
    }
    inline int lca(int u, int v, int s = 0x3f3f3f3f)
    {
        if (dep[u] < dep[v]) std::swap(u, v);
        while (dep[u] > dep[v])
        {
            s = std::min(s, f[u][lg[dep[u] - dep[v]]][1]);
            u = f[u][lg[dep[u] - dep[v]]][0];
        }
        if (u == v) return s;
        for (register int i = lg[dep[u]] + 1; i--; )
            if (f[u][i][0] ^ f[v][i][0])
            {
                s = std::min(s, f[u][i][1]);
                s = std::min(s, f[v][i][1]);
                u = f[u][i][0];
                v = f[v][i][0];
            }
        s = std::min(s, f[u][0][1]);
        s = std::min(s, f[v][0][1]);
        return s;
    }
    int main()
    {
        scanf("%d%d", &n, &m);
        for (register int i = 1; i <= n; ++i) fa[i] = i;
        for (register int i = 2; i <= n; ++i) lg[i] = lg[i >> 1] + 1;
        for (register int i = 1; i <= m; ++i)
            scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
        std::sort(e + 1, e + m + 1, cmp);
        for (register int i = 1; i <= m; ++i)
        {
            xx = find(e[i].u);
            yy = find(e[i].v);
            if (xx != yy)
            {
                fa[xx] = yy;
                add_edge(e[i].u, e[i].v, e[i].w);
                add_edge(e[i].v, e[i].u, e[i].w);
            }
        }
        for (register int i = 1; i <= n; ++i) if (!dep[i]) dfs(i);
        scanf("%d", &q);
        for (register int i = 1; i <= q; ++i)
        {
            scanf("%d%d", &u, &v);
            if (find(u) != find(v)) printf("-1
    ");
            else printf("%d
    ", lca(u, v));
        }
    }
    
  • 相关阅读:
    Django学习案例一(blog):四. 使用Admin
    Django学习案例一(blog):三. 模型生成数据
    Django学习案例一(blog):二. 连接数据库
    连接Xively云
    undefined reference to `_sbrk', `_write', `_lseek', `_read'
    Android manifest
    关于android socket出现at java.net.DatagramSocket java.net.BindException at libcore.io.IoBridge.bind(IoBridge.java:89)等waring
    virtual box Failed to load unit ""pgm" 的error
    Lwip lwip_recvfrom函数一个数据包不能分多次读取。
    获取Window下的文件缩略图
  • 原文地址:https://www.cnblogs.com/xuyixuan/p/9696620.html
Copyright © 2020-2023  润新知