标签:
题意:先给一棵树,然后有一条额外的边,问u走到v从现在最短的路走和原来不加边走的路节省了多少距离
分析:首先跑不加边的树的LCA,这样能求出任意两点的距离,那么现在x和y多连了一条边,如果能节省路程那一定是走了xy这条边,那么暴力枚举组合,比如求u到v,新边xy,ans = min (ans, min (dux + dxy + dyv, duy + dyx + dxv))
#include <cstdio> #include <algorithm> #include <cstring> #include <vector> #include <queue> using namespace std; typedef long long ll; const int N = 1e5 + 10; const int D = 20; const int INF = 0x3f3f3f3f; struct Edge { int v, w, nex; Edge (int v = 0, int w = 0, int nex = 0) : v (v), w (w), nex (nex) {} }edge[N<<1]; int head[N], dep[N], rt[D][N]; int d[N]; int n, q, e; int x, y, cost; void init(void) { memset (head, -1, sizeof (head)); e = 0; } void add_edge(int u, int v, int w) { edge[e] = Edge (v, w, head[u]); head[u] = e++; } void DFS(int u, int fa, int deep, int len) { dep[u] = deep; d[u] = len; rt[0][u] = fa; for (int i=head[u]; ~i; i=edge[i].nex) { int v = edge[i].v, w = edge[i].w; if (v == fa) continue; DFS (v, u, deep + 1, len + w); } } int LCA(int u, int v) { if (dep[u] < dep[v]) swap (u, v); for (int i=0; i<D; ++i) { if ((dep[u] - dep[v]) >> i & 1) { u = rt[i][u]; } } if (u == v) return u; for (int i=D-1; i>=0; --i) { if (rt[i][u] != rt[i][v]) { u = rt[i][u]; v = rt[i][v]; } } return rt[0][u]; } int solve(int u, int v) { int lca = LCA (u, v); int ans = d[u] + d[v] - d[lca] * 2; int lca1 = LCA (u, x); int dux = d[u] + d[x] - d[lca1] * 2; int lca2 = LCA (u, y); int duy = d[u] + d[y] - d[lca2] * 2; int lca3 = LCA (v, x); int dvx = d[v] + d[x] - d[lca3] * 2; int lca4 = LCA (v, y); int dvy = d[v] + d[y] - d[lca4] * 2; int mn = min (dux + dvy + cost, duy + dvx + cost); if (mn > ans) return 0; else return ans - mn; } int main(void) { int T, cas = 0; scanf ("%d", &T); while (T--) { init (); scanf ("%d%d", &n, &q); for (int u, v, w, i=1; i<n; ++i) { scanf ("%d%d%d", &u, &v, &w); add_edge (u, v, w); add_edge (v, u, w); } scanf ("%d%d%d", &x, &y, &cost); DFS (1, -1, 0, 0); for (int i=1; i<D; ++i) { for (int j=1; j<=n; ++j) { rt[i][j] = rt[i-1][j] == -1 ? -1 : rt[i-1][rt[i-1][j]]; } } printf ("Case #%d:\n", ++cas); for (int u, v, i=1; i<=q; ++i) { scanf ("%d%d", &u, &v); printf ("%d\n", solve (u, v)); } } return 0; }
标签:
原文地址:http://www.cnblogs.com/Running-Time/p/4861585.html