萌新刚学OI求调
查看原帖
萌新刚学OI求调
610557
shinzanmonoszm 妹妹楼主2022/10/7 12:32
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using piit = pair<ll, int>;
const ll inf = numeric_limits<ll>::max() / 2;
const int sz = 1e5 + 10;
const int lgsz = __lg(sz) + 1;
struct edge_k {
    int u, v;
    ll w;
    bool operator<(const edge_k &a) const {
        return w < a.w;
    }
} graph_k[sz];
struct edge {
    int nxt, to;
    ll w;
} tree[sz], graph[100];
int hppt, hppg, headt[sz], headg[sz];
void addEdge(int u, int v, ll weight, edge* g, int& hpp, int* head) {
    g[++hpp] = edge{head[u], v, weight};
    head[u] = hpp;
    g[++hpp] = edge{head[v], u, weight};
    head[v] = hpp;
}
struct UFS {
    vector<int> fa, ssz;
    void clear(int n) {
        fa.resize(n + 1), ssz.resize(n + 1, 1);
        for (int i = 1; i <= n; i++) fa[i] = i;
    }
    int find(int u) {
        if (fa[u] == u) return fa[u];
        return fa[u] = find(fa[u]);
    }
    bool merge(int u, int v) {
        int fu = find(u), fv = find(v);
        if (fu == fv) return false;
        if (ssz[fu] > ssz[fv]) swap(fu, fv);
        fa[fu] = fv, ssz[fv] += ssz[fu];
        return true;
    }
} ufs;
int n, m;
map<int, int> ma;
int pts[50], cnt;
void kruskal() {
    ufs.clear(n);
    sort(graph_k + 1, graph_k + m + 1);
    for (int i = 1; i <= m; i++) {
        int u = graph_k[i].u, v = graph_k[i].v;
        if (!ufs.merge(u, v)) {
            if (!ma[u]) ma[u] = ++cnt, pts[cnt] = u;
            if (!ma[v]) ma[v] = ++cnt, pts[cnt] = v;
            continue;
        }
        addEdge(u, v, graph_k[i].w, tree, hppt, headt);
    }
}
int f[lgsz][sz], dpp, dfn[sz], dep[sz];
ll tdis[sz];
void dfs(int u, int fa, ll w) {
    dfn[u] = ++dpp, f[0][dpp] = fa, dep[u] = dep[fa] + 1, tdis[u] = tdis[fa] + w;
    for (int p = headt[u]; p; p = tree[p].nxt) {
        int v = tree[p].to;
        if (v != fa) dfs(v, u, tree[p].w);
    }
}
int depmin(int u, int v) {
    return dep[u] < dep[v] ? u : v;
}
void init() {
    for (int i = 1; i <= __lg(n); i++)
        for (int j = 1; j + (1 << i) - 1 <= n; j++)
            f[i][j] = depmin(f[i - 1][j], f[i - 1][j + (1 << i - 1)]);
}
int lca(int u, int v) {
    int du = dfn[u], dv = dfn[v];
    if (du > dv) swap(du, dv);
    int lg = __lg(dv - du);
    return depmin(f[lg][du + 1], f[lg][dv - (1 << lg) + 1]);
}
ll dis[50][sz];
bool vis[sz];
priority_queue<piit, vector<piit>, greater<piit>> pq;
void dijkstra(int s) {
    fill(dis[ma[s]] + 1, dis[ma[s]] + n + 1, inf);
    memset(vis, 0, sizeof vis);
    dis[ma[s]][s] = 0, pq.push(make_pair(dis[ma[s]][s], s));
    while (!pq.empty()) {
        int u = pq.top().second;
        pq.pop();
        if (vis[u]) continue;
        vis[u] = true;
        for (int p = headg[u]; p; p = graph[p].nxt) {
            int v = graph[p].to;
            if (dis[ma[s]][v] > dis[ma[s]][u] + graph[p].w) {
                dis[ma[s]][v] = dis[ma[s]][u] + graph[p].w;
                pq.push(make_pair(dis[ma[s]][v], v));
            }
        }
    }
}
int main() {
    ios::sync_with_stdio(false);
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        int u, v, d;
        cin >> u >> v >> d;
        graph_k[i] = edge_k{u, v, d};
        addEdge(u, v, d, graph, hppg, headg);
    }
    kruskal();
    dfs(1, 1, 0);
    init();
    for (int i = 1; i <= cnt; i++)
        dijkstra(pts[cnt]);
    int q;
    cin >> q;
    while (q--) {
        int u, v;
        cin >> u >> v;
        int l = lca(u, v);
        ll ans = inf << 1;
        for (int i = 1; i <= cnt; i++)
            ans = min(ans, dis[i][u] + dis[i][v]);
        cout << min(tdis[u] + tdis[v] - 2 * tdis[l], ans) << endl;
    }
    return 0;
}
2022/10/7 12:32
加载中...