• CF1051F The Shortest Statement 题解


    题目

    You are given a weighed undirected connected graph, consisting of n vertices and m edges.

    You should answer q queries, the i-th query is to find the shortest distance between vertices (u_i) and (v_i).

    输入格式

    The first line contains two integers (n) and (m (1≤n,m≤105,m−n≤20)) — the number of vertices and edges in the graph.

    Next m lines contain the edges: the i-th edge is a triple of integers (v_i,u_i,d_i (1≤u_i,v_i≤n,1≤d_i≤10^9,u_i≠v_i)). This triple means that there is an edge between vertices ui and vi of weight di. It is guaranteed that graph contains no self-loops and multiple edges.

    The next line contains a single integer (q (1≤q≤10^5)) — the number of queries.

    Each of the next q lines contains two integers (u_i) and (v_i (1≤u_i,v_i≤n)) — descriptions of the queries.

    Pay attention to the restriction (m−n ≤ 20).

    输出格式

    Print q lines.

    The i-th line should contain the answer to the i-th query — the shortest distance between vertices (u_i) and (v_i).

    输入样例1

    3 3
    1 2 3
    2 3 1
    3 1 5
    3
    1 2
    1 3
    2 3
    

    输出样例1

    3
    4
    1
    

    输入样例2

    8 13
    1 2 4
    2 3 6
    3 4 1
    4 5 12
    5 6 3
    6 7 8
    7 8 7
    1 4 1
    1 8 3
    2 6 9
    2 7 1
    4 6 3
    6 8 2
    8
    1 5
    1 7
    2 3
    2 8
    3 7
    3 4
    6 8
    7 8
    

    输出样例2

    7
    5
    6
    7
    7
    1
    2
    7
    

    题解

    由于(m−n ≤ 20), 边和点的数量接近, 所以大部分最短路用lca解决, 剩下的一些没有计算的边, 对它们的顶点重新跑一遍最短路, 然后枚举每一个点, 更新两个目标点之间的最短距离.

    代码

    #include <cstdio>
    #include <algorithm>
    #include <queue>
    using namespace std;
    const long long INF = 1e18;
    const int N = 100005;
    int head[N], tote, f[N][21], deth[N], tmp[100], tot, n, m;
    long long dis[N], d[50][N];
    bool vis[N];
    struct Edge { int to, next, value; } edges[N << 1];
    void add(int u, int v, int w) {
        edges[++tote]= (Edge){ v, head[u], w}, head[u] = tote;
        edges[++tote]= (Edge){ u, head[v], w}, head[v] = tote;
    }
    priority_queue<pair<long long, int>, vector<pair<long long, int> >, greater<pair<long long, int> > > q;
    void dijkstra(int id, int S) {
        for (int i = 1; i <= n; ++i) dis[i] = INF, vis[i] = false;
        dis[S] = 0;
        q.push(make_pair(0, S));
        while (!q.empty()) {
            int u = q.top().second;
            q.pop();
            if (vis[u]) continue;
            vis[u] = true;
            for (int i = head[u]; i; i = edges[i].next) {
                int v = edges[i].to;
                if (dis[v] > dis[u] + edges[i].value) {
                    dis[v] = dis[u] + edges[i].value;
                    q.push(make_pair(dis[v], v));
                }
            }
        }
        for (int i = 1; i <= n; ++i) d[id][i] = dis[i];
    }
    void dfs(int u, int fa) {
        vis[u] = true;
        f[u][0] = fa;
        deth[u] = deth[fa] + 1;
        for (int i = head[u]; i; i = edges[i].next) {
            int v = edges[i].to;
            if (v == fa) continue;
            if (vis[v]) tmp[++tot] = u, tmp[++tot] = v;
            else dis[v] = dis[u] + edges[i].value, dfs(v, u);
        }
    }
    int lca(int u, int v) {
        if (deth[u] < deth[v]) swap(u, v);
        int d = deth[u] - deth[v];
        for (int i = 20; i >= 0; --i)
            if (d & (1 << i)) u = f[u][i];
        if (u == v) return u;
        for (int i = 20; i >= 0; --i)
            if (f[u][i] != f[v][i]) u = f[u][i], v = f[v][i];
        return f[u][0];
    }
    inline int input() { int t; scanf("%d", &t); return t; }
    int main() {
        n = input(), m = input();
        for (int i = 1; i <= m; ++i){
            int u = input(), v = input(), w = input();
            add(u, v, w);
        }
        dfs(1, 0);
        for (int i = 1; i <= n; ++i) d[0][i] = dis[i];
        for (int j = 1; j <= 20; ++j)
            for (int i = 1; i <= n; ++i) f[i][j] = f[f[i][j - 1]][j - 1];
        sort(tmp + 1, tmp + tot + 1);
        int j = 1;
        for (int i = 2; i <= tot; ++i)
            if (tmp[j] != tmp[i]) tmp[++j] = tmp[i];
        for (int i = 1; i <= j; ++i) dijkstra(i, tmp[i]);
        for(int q = input(); q; q--) {
            int u = input(), v = input();
            long long ans = d[0][u] + d[0][v] - 2 * d[0][lca(u, v)];
            for (int i = 1; i <= j; ++i) ans = min(ans, d[i][u] + d[i][v]);
            printf("%lld
    ", ans);
        }
        return 0;
    }
    
  • 相关阅读:
    Python中的生成器
    API测试的五大好处
    Python可变参数*args和**kwargs
    Python中的迭代器
    docker下php安装imagick扩展
    docker端口映射不生效
    mysql学习笔记(一)一条sql查询语句是如何执行的
    lavavel学习笔记(一)安装
    mysql学习笔记(四)索引
    mysql学习笔记(二)一条sql更新语句是如何执行的
  • 原文地址:https://www.cnblogs.com/youxam/p/cf1051F.html
Copyright © 2020-2023  润新知