The Shortest Statement

ps:非常非常重要的一个条件 m - n <= 20,考虑图的生成树,那么(u,v)之间的最短路上的边有两种情况,一是最短路不经过非生成树的边,二是经过非生成树的边。又非生成树的边只有20条,则连接的点最多有40个,所以对这40个点分别跑一次DJS,然后取最小值就行了。(换言之:如果最短路经过非生成树边,那么我们就可以枚举这些边)

const int N = 100005;

int n, m, tot, top;
int head[N], pa[N][20], dp[N], tp[100];

LL d[N][55];

bool use[N];

struct node { int to, va, next; } e[N * 2];

priority_queue<P, vector<P>, greater<P> > q;

void Inite() {
    top = tot = 0;
    mem(head, -1);
    Rep(i, 1, n) Rep(j, 1, 50) d[i][j] = INF64;
}

void addedge(int u, int v, int w) {
    e[tot].to = v, e[tot].va = w, e[tot].next = head[u], head[u] = tot++;
}

void DFS(int u, int p) {
    use[u] = 1;
    pa[u][0] = p;
    for (int i = head[u]; ~i; i = e[i].next) if (e[i].to != p) {
        int v = e[i].to;
        if (use[v]) tp[++top] = v, tp[++top] = u;
        else {
            dp[v] = dp[u] + 1;
            d[v][0] = d[u][0] + e[i].va;
            DFS(v, u);
        }
    }
}

int Lca(int u, int v) {
    if (u == v) return u;
    if (dp[u] > dp[v]) swap(u, v);

    for (int i = 19; ~i; --i) if (dp[pa[v][i]] >= dp[u]) v = pa[v][i];
    //rep(i, 0, 20) if (((1 << i) & (dp[v] - dp[u])) == 1) v = pa[v][i];
    if (u == v) return u;

    for (int i = 19; ~i; --i) if (pa[u][i] != pa[v][i]) {
        u = pa[u][i];
        v = pa[v][i];
    }
    return pa[u][0];
}

void Compute(int id) {
    while(!q.empty()) q.pop();
    bool vis[N];
    mem(vis, 0);

    d[tp[id]][id] = 0;
    q.push(P(0, tp[id]));

    while(!q.empty()) {
        P p = q.top();
        q.pop();

        int v = p.second;
        if (vis[v]) continue;
        vis[v] = 1;

        for (int i = head[v]; ~i; i = e[i].next) if (d[e[i].to][id] > d[v][id] + e[i].va) {
            d[e[i].to][id] = d[v][id] + e[i].va;
            q.push(P(d[e[i].to][id], e[i].to));
        }
    }
}

int main()
{
    sc(n), sc(m);

    Inite();
    Rep(i, 1, m) {
        int u, v, w;
        sc(u), sc(v), sc(w);
        addedge(u, v, w);
        addedge(v, u, w);
    }

    DFS(1, 0);
    Rep(i, 1, 19) Rep(j, 1, n) if (pa[j][i - 1]) pa[j][i] = pa[pa[j][i - 1]][i - 1];

    sort(tp + 1, tp + top + 1);
    top = unique(tp + 1, tp + top + 1) - (tp + 1);

    Rep(i, 1, top) Compute(i);

    int cnt;
    sc(cnt);

    while(cnt--) {
        int u, v;
        sc(u), sc(v);

        int p = Lca(u, v);
        LL ans = d[u][0] + d[v][0] - 2 * d[p][0];

        Rep(i, 1, top) ans = min(ans, d[u][i] + d[v][i]);
        pr(ans);
    }

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zgglj-com/p/9696288.html