CF1051F The Shortest Statement
CF链接:CF1051F The Shortest Statement
洛谷链接:CF1051F The Shortest Statement
缝合怪,普及题
第一眼不可做,第二眼 \(N - M \le 20\) 那么考虑一个树上挂了20条边,直接先整一颗树,对于多余的边的两个端点,每个跑一遍Dijkstra。
查询的时候直接取最小就好了。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MAXN = 1e5+10;
struct edge {
ll nt, to, v;
} E[MAXN << 1];
struct heap {
ll dis, v;
friend bool operator < (heap a, heap b) {
return a.dis > b.dis;
}
};
bool vis[MAXN], used[MAXN << 1];
ll N, M, head[MAXN], dep[MAXN], cnt = -1, Q, fa[22][MAXN], dis[22][MAXN], di[44][MAXN];
vector <ll> q;
void add(ll, ll, ll);
void dfs(ll);
void dik(ll, ll);
ll lca(ll, ll);
int main() {
memset(head, -1, sizeof(head));
scanf("%lld%lld", &N, &M);
for (ll i = 1, x, y, v; i <= M; i++) {
scanf("%lld%lld%lld", &x, &y, &v);
add(x, y, v);
add(y, x, v);
}
dfs(1);
for (ll i = 1; i <= M * 2; i++) {
if (!used[i]) {
used[i] = used[i ^ 1] = 1;
q.push_back(E[i].to);
q.push_back(E[i ^ 1].to);
}
}
sort(q.begin(), q.end());
q.erase(unique(q.begin(), q.end()), q.end());
for (ll i = 0; i < (ll)q.size(); i++) {
dik(q.at(i), i+1);
}
scanf("%lld", &Q);
for (ll i = 1, a, b; i <= Q; i++) {
scanf("%lld%lld", &a, &b);
//dst...
ll san = lca(a, b);
for (ll i = 0; i < (ll)q.size(); i++) {
san = min(san, di[i+1][a] + di[i+1][b]);
}
printf("%lld\n", san);
}
return 0;
}
ll lca(ll x, ll y) {
ll ret = 0;
if (dep[x] < dep[y]) {
swap(x, y);
}
ll hi = dep[x] - dep[y];
for (ll i = 20; ~i; i--) {
if ((hi >> i) & 1) {
ret += dis[i][x];
x = fa[i][x];
}
}
if (x == y) return ret;
for (ll i = 20; ~i; i--) {
if (fa[i][x] != fa[i][y]) {
ret += dis[i][x];
ret += dis[i][y];
x = fa[i][x];
y = fa[i][y];
}
}
return ret + dis[0][x] + dis[0][y];
}
void dik(ll st, ll id) {
priority_queue <heap> now;
now.push({0, st});
for (ll i = 1; i <= N; i++) vis[i] = 0, di[id][i] = INF;
di[id][st] = 0;
while (!now.empty()) {
heap nt = now.top(); now.pop();
if (vis[nt.v]) continue;
for (ll i = head[nt.v]; ~i; i = E[i].nt) {
ll v = E[i].to;
if (di[id][v] > di[id][nt.v] + E[i].v) {
di[id][v] = di[id][nt.v] + E[i].v;
now.push({di[id][v], v});
}
}
}
}
void dfs(ll n) {
vis[n] = 1;
for (ll i = 1; i <= 20; i++) {
fa[i][n] = fa[i-1][fa[i-1][n]];
dis[i][n] = dis[i-1][fa[i-1][n]] + dis[i-1][n];
}
for (ll i = head[n]; ~i; i = E[i].nt) {
ll v = E[i].to;
if (vis[v]) continue;
used[i] = used[i ^ 1] = 1;
fa[0][v] = n;
dis[0][v] = E[i].v;
dep[v] = dep[n] + 1;
dfs(v);
}
}
void add(ll x, ll y, ll v) {
cnt++;
E[cnt].to = y;
E[cnt].nt = head[x];
head[x] = cnt;
E[cnt].v = v;
}
希望我们都有一个光明的未来

浙公网安备 33010602011771号