HDU-2874 Connections between cities
Connections between cities
LCA 倍增板子
求距离维护一个前缀和,\(dis(u, v) = dis(rt, u) + dis(rt, v) - dis(rt, lca) * 2\)
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
#define pii pair<int, ll>
const int maxn = 1e4 + 10;
vector<pii>gra[maxn];
int vis[maxn], fa[maxn][15], dep[maxn];
ll sum[maxn];
void dfs(int now, int pre, int d)
{
if(vis[now]) return;
vis[now] = 1;
fa[now][0] = pre;
dep[now] = d;
for(pii &a : gra[now])
{
if(a.first == pre) continue;
sum[a.first] += sum[now] + a.second;
dfs(a.first, now, d + 1);
}
}
void init(int n)
{
for(int i=0; i<=n; i++) dep[i] = sum[i] = vis[i] = 0;
for(int i=1; i<=n; i++) dfs(i, i, 1);
for(int i=1; i<15; i++)
for(int j=1; j<=n; j++)
fa[j][i] = fa[fa[j][i - 1]][i - 1];
for(int i=0; i<=n; i++) gra[i].clear();
}
int LCA(int u, int v)
{
if(dep[u] < dep[v]) swap(u, v);
int dif = dep[u] - dep[v];
for(int i=14; i>=0; i--)
{
if(dif >= (1 << i))
{
dif -= 1 << i;
u = fa[u][i];
}
}
if(u == v) return u;
for(int i=14; i>=0; i--)
{
if(fa[u][i] != fa[v][i])
{
u = fa[u][i];
v = fa[v][i];
}
}
return fa[u][0];
}
ll dis(int u, int v)
{
int lca = LCA(u, v);
return sum[u] - sum[lca] * 2 + sum[v];
}
int main()
{
int n, m, q;
while(scanf("%d%d%d", &n, &m, &q) != EOF)
{
for(int i=0; i<m; i++)
{
int a, b;
ll c;
scanf("%d%d%lld", &a, &b, &c);
gra[a].push_back({b, c});
gra[b].push_back({a, c});
}
init(n);
while(q--)
{
int u, v;
scanf("%d%d", &u, &v);
if(fa[u][14] != fa[v][14]) printf("Not connected\n");
else printf("%lld\n", dis(u, v));
}
}
return 0;
}