Traffic Network in Numazu
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 200 Accepted Submission(s): 70
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 nodes and N edges, and you have to finish Q missions. Each mission consists of 3 integers OP, X and Y.
When OP=0, you need to modify the weight of the Xth edge to Y.
When OP=1, you need to calculate the length of the shortest path from node X to node Y.
Input
The first line contains a single integer T, the number of test cases.
Each test case starts with a line containing two integers N and Q, the number of nodes (and edges) and the number of queries. (3≤N≤105)(1≤Q≤105)
Each of the following N lines contain the description of the edges. The ith line represents the ith edge, which contains 3 space-separated integers ui, vi, and wi. This means that there is an undirected edge between nodes ui and vi, with a weight of wi. (1≤ui,vi≤N)(1≤wi≤105)
Then Q lines follow, the ith line contains 3 integers OP, X and Y. The meaning has been described above.(0≤OP≤1)(1≤X≤105)(1≤Y≤105)
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, print one line containing one integer, the length of the shortest path between X and Y.
Sample Input
2 5 5 1 2 3 2 3 5 2 4 5 2 5 1 4 3 3 0 1 5 1 3 2 1 5 4 0 5 4 1 5 1 5 3 1 2 3 1 3 2 3 4 4 4 5 5 2 5 5 0 1 3 0 4 1 1 1 4
Sample Output
5 6 6 6
传送门:HDU-6393
题意:有一个基环树,有两种操作:修改一条边的长度,查询两点间的最短路径
题解:可以看成一个环加上若干个树,分成两部分考虑,在树上用树剖维护,在环上用树状数组维护。
#include <bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define x first
#define y second
#define rep(i,a,b) for(int i=a;i<b;++i)
#define per(i,a,b) for(int i=a-1;i>=b;--i)
#define fuck(x) cout<<'['<<#x<<' '<<(x)<<']'
#define FIN freopen("in.txt","r",stdin);
#define eps 1e-8
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> VI;
typedef pair<int, int> PII;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fll;
const int MX = 1e5 + 5;
struct Edge {
int v, w, nxt;
} E[MX << 1];
int head[MX], tot, IN[MX];
bool vis[MX];
void init(int n) {
rep(i, 1, n + 1) vis[i] = IN[i] = 0, head[i] = -1;
tot = 0;
}
inline void edge_add(int u, int v, int w) {
E[tot] = (Edge) {v, w, head[u]}, head[u] = tot++;
IN[v]++;
}
int rt[MX];
struct Tree {
int f[MX], p[MX], sz[MX], son[MX], top[MX], dep[MX], totp;
ll sum[MX << 2], d[MX];
void dfs(int u, int fa, int deep, int root) {
f[u] = fa; dep[u] = deep;
son[u] = 0; sz[u] = 1;
rt[u] = root;
for (int i = head[u]; ~i; i = E[i].nxt) {
int v = E[i].v;
if (v == fa || !vis[v]) continue;
dfs(v, u, deep + 1, root);
sz[u] += sz[v];
if (sz[son[u]] < sz[v]) son[u] = v;
}
}
void rebuild(int u, int t) {
top[u] = t; p[u] = totp++;
if (son[u]) rebuild(son[u], t);
for (int i = head[u]; ~i; i = E[i].nxt) {
int v = E[i].v;
if (v == f[u] || !vis[v]) continue;
if (v == son[u]) {
d[p[v]] = E[i].w;
continue;
}
rebuild(v, v);
d[p[v]] = E[i].w;
}
}
void prebuild(int n) {
totp = 1;
rep(i, 1, n + 1) if(!vis[i]) {
dfs(i, 0, 1, i);
rebuild(i, 1);
}
build(1, totp - 1, 1);
}
inline void PushUP(int rt) {
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
void build(int l, int r, int rt) {
if (l == r) {
sum[rt] = d[l];
return;
}
int m = (l + r) >> 1;
build(lson), build(rson);
PushUP(rt);
}
void update(int p, int c, int l, int r, int rt) {
if (l == r) {
sum[rt] = c;
return;
}
int m = (l + r) >> 1;
if (p <= m) update(p, c, lson);
else update(p, c, rson);
PushUP(rt);
}
ll query(int L, int R, int l, int r, int rt) {
if (L <= l && R >= r) return sum[rt];
int m = (l + r) >> 1;
ll ret = 0;
if (L <= m) ret += query(L, R, lson);
if (R > m) ret += query(L, R, rson);
return ret;
}
ll solve(int u, int v) {
int f1 = top[u], f2 = top[v];
ll ans = 0;
while (f1 != f2) {
if (dep[f1] < dep[f2]) {
swap(f1, f2);
swap(u, v);
}
ans += query(p[f1], p[u], 1, totp - 1, 1);
u = f[f1]; f1 = top[u];
}
if (u != v) {
if (dep[u] > dep[v]) swap(u, v);
ans += query(p[son[u]], p[v], 1, totp - 1, 1);
}
return ans;
}
inline void Update(int u, int v, int val) {
if(u == f[v]) swap(u, v);
update(p[u], val, 1, totp - 1, 1);
}
} t;
struct BitTree {
int n;
vector <ll> T;
void init (int _n) {
if (T.empty()) T.resize(MX);
else for (int i = 0; i <= _n; i++) T[i] = 0;
n = _n;
}
void add(int x, ll v) {
for (int i = x; i <= n; i += i & -i) T[i] += v;
}
ll sum(int x) {
if (x > n) x = n;
ll ret = 0;
for (int i = x; i > 0; i -= i & -i) ret += T[i];
return ret;
}
} bt;
int n, m;
PII edge[MX];
int ew[MX], dfn[MX], dfn_cnt, par;
bool mark[MX];
void search(int u, int pre) {
dfn[u] = ++dfn_cnt;
for(int i = head[u]; ~i; i = E[i].nxt) {
int v = E[i].v, w = E[i].w;
if(v == pre || vis[v]) continue;
bt.add(dfn[u], w);
if(v == par) break;
search(v, u);
break;
}
}
void pre_solve() {
queue<int>q;
rep(i, 1, n + 1) if(IN[i] == 1) q.push(i);
while(!q.empty()) {
int u = q.front(); q.pop();
vis[u] = 1;
for(int i = head[u]; ~i; i = E[i].nxt) {
int v = E[i].v;
IN[v]--;
if(IN[v] == 1) q.push(v);
}
}
t.prebuild(n);
rep(i, 1, n + 1) if(!vis[edge[i].x] && !vis[edge[i].y]) mark[i] = 1;
dfn_cnt = 0, bt.init(n);
rep(i, 1, n + 1) if(!vis[i]) {par = i; search(i, i); break;}
}
int main() {
#ifdef local
FIN;
#endif
int cas; cin >> cas;
while (cas--) {
scanf("%d%d", &n, &m);
init(n);
int u, v, w;
rep(i, 1, n + 1) {
scanf("%d%d%d", &u, &v, &w);
edge_add(u, v, w);
edge_add(v, u, w);
edge[i] = PII(u, v);
mark[i] = 0;
ew[i] = w;
}
pre_solve();
int op, x, y;
rep(i, 0, m) {
scanf("%d%d%d", &op, &x, &y);
if(op == 0) {
u = edge[x].x, v = edge[x].y;
if(mark[x]) {
if(dfn[u] > dfn[v]) swap(u, v);
if(dfn[u] == 1 && dfn[v] == dfn_cnt) bt.add(dfn[v], y - ew[x]);
else bt.add(dfn[u], y - ew[x]);
ew[x] = y;
} else t.Update(u, v, y);
} else {
if(rt[x] == rt[y]) printf("%lld\n", t.solve(x, y));
else {
ll ans = 0;
if(x != rt[x]) ans += t.solve(x, rt[x]);
if(y != rt[y]) ans += t.solve(y, rt[y]);
x = rt[x], y = rt[y];
if(dfn[x] > dfn[y]) swap(x, y);
ll tmp = bt.sum(dfn[y] - 1) - bt.sum(dfn[x] - 1);
tmp = min(tmp, bt.sum(dfn_cnt) - tmp);
printf("%lld\n", ans + tmp);
}
}
}
}
return 0;
}