概述
题解链接
https://www.lucien.ink/archives/315/
题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=6393
题目
Problem Description
Chika is elected mayor of Numazu. She needs to manage the traffic in this city. To manage the traffic is too hard for her. So she needs your help.
You are given the map of the city —— an undirected connected weighted graph with
N
N
nodes and edges, and you have to finish
Q
Q
missions. Each mission consists of integers
OP
O
P
,
X
X
and .
When
OP=0
O
P
=
0
, you need to modify the weight of the
Xth
X
t
h
edge to
Y
Y
.
When , you need to calculate the length of the shortest path from node
X
X
to node .
Input
The first line contains a single integer
T
T
, the number of test cases.
Each test case starts with a line containing two integers and
Q
Q
, the number of nodes (and edges) and the number of queries.
Each of the following
N
N
lines contain the description of the edges. The line represents the
ith
i
t
h
edge, which contains
3
3
space-separated integers ,
vi
v
i
, and
wi
w
i
. This means that there is an undirected edge between nodes
ui
u
i
and
vi
v
i
, with a weight of
wi
w
i
.
(1≤ui,vi≤N)(1≤wi≤105)
(
1
≤
u
i
,
v
i
≤
N
)
(
1
≤
w
i
≤
10
5
)
Then Q lines follow, the ith line contains
3
3
integers ,
X
X
and . The meaning has been described above.
(0≤OP≤1)(1≤X≤105)(1≤Y≤105)
(
0
≤
O
P
≤
1
)
(
1
≤
X
≤
10
5
)
(
1
≤
Y
≤
10
5
)
It is guaranteed that the graph contains no self loops or multiple edges.
Output
For each test case, and for each mission whose OP=1 O P = 1 , print one line containing one integer, the length of the shortest path between X X and .
题意
给你 N N 个点条边的有权无向图,有两种询问, op=0 o p = 0 代表把第 X X 条边的权值改为, op=1 o p = 1 代表查询点点 X X 到点的最短路。
思路
可以观察所给的图是一棵基环树,可以将环的某一条边断开,通过树状数组来维护树上距离。这样一来两个点的最短路就是点到环的距离加上环内的距离。
实现
#include <bits/stdc++.h>
typedef long long ll;
const int maxn = int(1e5) + 7;
int swap(int &a, int &b, int c = 0) { c = a, a = b, b = c; }
struct Bit {
ll data[maxn];
int len;
void init(int len_) { len = len_, memset(data, 0, sizeof(data)); }
void add(int pos, int val) { while (pos <= len) data[pos] += val, pos += pos & -pos; }
ll query(int pos) {
ll ret = 0;
while (pos) ret += data[pos], pos -= pos & -pos;
return ret;
}
} bit;
struct Edge { int u, v, val; } edge[maxn];
std::vector<int> edges[maxn];
int t, n, q, base, l[maxn], r[maxn], dep[maxn], up[maxn][20], dfn;
bool visNode[maxn], visEdge[maxn];
void dfs(int u, int pre = 0, int val = 0) {
visNode[u] = true;
dep[u] = dep[pre] + 1;
l[u] = ++dfn;
bit.add(dfn, val);
for (int i : edges[u]) {
if (edge[i].u == pre) continue;
if (edge[i].v == u) swap(edge[i].u, edge[i].v);
if (visNode[edge[i].v]) continue;
visEdge[i] = true;
up[edge[i].v][0] = u;
dfs(edge[i].v, u, edge[i].val);
}
r[u] = dfn;
bit.add(dfn + 1, -val);
}
void init(int n) {
dfn = 0;
bit.init(n);
memset(visNode, 0, sizeof(visNode));
memset(visEdge, 0, sizeof(visEdge));
memset(up, 0xff, sizeof(up));
for (int i = 1; i <= n; i++) edges[i].clear();
}
void process(int n) {
dfs(1);
for (int j = 1; j <= 18; j++)
for (int i = 1; i <= n; i++)
if (~up[i][j - 1])
up[i][j] = up[up[i][j - 1]][j - 1];
}
int lca(int u, int v) {
if (dep[u] < dep[v]) swap(u, v);
int diff = dep[u] - dep[v];
for (int i = 0; diff; i++)
if (diff & (1 << i)) {
u = up[u][i];
diff ^= 1 << i;
}
if (u == v) return u;
for (int j = 18; j >= 0; j--)
if (up[u][j] != up[v][j])
u = up[u][j], v = up[v][j];
return up[u][0];
}
void update(int x, int y) {
int u = edge[x].v, diff = y - edge[x].val;
bit.add(l[u], diff);
bit.add(r[u] + 1, -diff);
edge[x].val = y;
}
ll lcaDist(int u, int v) {
return bit.query(l[u]) + bit.query(l[v]) - bit.query(l[lca(u, v)]) * 2;
}
ll query(int u, int v) {
ll ret = lcaDist(u, v), dist[2];
dist[0] = lcaDist(u, edge[base].u);
dist[1] = lcaDist(v, edge[base].v);
ret = std::min(ret, dist[0] + dist[1] + edge[base].val);
dist[0] = lcaDist(u, edge[base].v);
dist[1] = lcaDist(v, edge[base].u);
ret = std::min(ret, dist[0] + dist[1] + edge[base].val);
return ret;
}
int main() {
for (scanf("%d", &t); t; t--) {
scanf("%d%d", &n, &q);
init(n);
for (int i = 1, u, v, val; i <= n; i++) {
scanf("%d%d%d", &u, &v, &val);
edge[i] = {u, v, val};
edges[u].push_back(i);
edges[v].push_back(i);
}
process(n);
for (int i = 1; i <= n; i++) if (!visEdge[i]) base = i;
for (int i = 1, op, x, y; i <= q; i++) {
scanf("%d%d%d", &op, &x, &y);
if (op == 0) update(x, y);
else printf("%lldn", query(x, y));
}
}
return 0;
}
最后
以上就是多情摩托为你收集整理的HDU-6393 - Traffic Network in Numazu - LCA & 树状数组的全部内容,希望文章能够帮你解决HDU-6393 - Traffic Network in Numazu - LCA & 树状数组所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复