过路费
Time Limit: 1000ms
Memory Limit: 32768KB
This problem will be judged on FZU. Original ID: 208264-bit integer IO format: %I64d Java class name: Main
有n座城市,由n-1条路相连通,使得任意两座城市之间可达。每条路有过路费,要交过路费才能通过。每条路的过路费经常会更新,现问你,当前情况下,从城市a到城市b最少要花多少过路费。
Input
有多组样例,每组样例第一行输入两个正整数$n,m(2 leq nleq 50000,1leq m leq 50000)$,接下来n-1行,每行3个正整数$a b c,(1leq a,bleq n , a != b , 1leq cleq 1000000000)$.数据保证给的路使得任意两座城市互相可达。接下来输入m行,表示m个操作。
操作有两种:
- 0 a b,表示更新第a条路的过路费为b,$1leq aleq n-1 $。
- 1 a b , 表示询问a到b最少要花多少过路费。
Output
对于每个询问,输出一行,表示最少要花的过路费。
Sample Input
2 3 1 2 1 1 1 2 0 1 2 1 2 1
Sample Output
1 2
Source
解题:树链剖分
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 const int maxn = 50010; 7 struct arc{ 8 int to,w,next; 9 arc(int x = 0,int y = 0,int z = -1){ 10 to = x; 11 w = y; 12 next = z; 13 } 14 }e[maxn<<1]; 15 int head[maxn],fa[maxn],top[maxn],dep[maxn]; 16 int son[maxn],siz[maxn],loc[maxn],clk,tot; 17 int tree[maxn<<2]; 18 void add(int u,int v,int w){ 19 e[tot] = arc(v,w,head[u]); 20 head[u] = tot++; 21 } 22 void FindHeavyEdge(int u,int father,int depth){ 23 fa[u] = father; 24 dep[u] = depth; 25 siz[u] = 1; 26 son[u] = -1; 27 for(int i = head[u]; ~i; i = e[i].next){ 28 if(e[i].to == father) continue; 29 FindHeavyEdge(e[i].to,u,depth + 1); 30 siz[u] += siz[e[i].to]; 31 if(son[u] == -1 || siz[e[i].to] > siz[son[u]]) 32 son[u] = e[i].to; 33 } 34 } 35 void ConnectHeavyEdge(int u,int ancestor){ 36 top[u] = ancestor; 37 loc[u] = clk++; 38 if(son[u] != -1) ConnectHeavyEdge(son[u],ancestor); 39 for(int i = head[u]; ~i; i = e[i].next){ 40 if(e[i].to == fa[u] || son[u] == e[i].to) continue; 41 ConnectHeavyEdge(e[i].to,e[i].to); 42 } 43 } 44 void update(int L,int R,int pos,int val,int v){ 45 if(L == R){ 46 tree[v] = val; 47 return; 48 } 49 int mid = (L + R)>>1; 50 if(pos <= mid) update(L,mid,pos,val,v<<1); 51 if(pos > mid) update(mid + 1,R,pos,val,v<<1|1); 52 tree[v] = tree[v<<1] + tree[v<<1|1]; 53 } 54 int query(int L,int R,int lt,int rt,int v){ 55 if(lt <= L && rt >= R) return tree[v]; 56 int mid = (L + R)>>1,ret = 0; 57 if(lt <= mid) ret = query(L,mid,lt,rt,v<<1); 58 if(rt > mid) ret += query(mid + 1,R,lt,rt,v<<1|1); 59 return ret; 60 } 61 int solve(int u,int v,int ret = 0){ 62 while(top[u] != top[v]){ 63 if(dep[top[u]] < dep[top[v]]) swap(u,v); 64 ret += query(0,clk-1,loc[top[u]],loc[u],1); 65 u = fa[top[u]]; 66 } 67 if(u == v) return ret; 68 if(dep[u] > dep[v]) swap(u,v); 69 ret += query(0,clk-1,loc[son[u]],loc[v],1); 70 return ret; 71 } 72 int main(){ 73 int n,m,u,v,w,op; 74 while(~scanf("%d%d",&n,&m)){ 75 memset(head,-1,sizeof head); 76 clk = tot = 0; 77 for(int i = 1; i < n; ++i){ 78 scanf("%d%d%d",&u,&v,&w); 79 add(u,v,w); 80 add(v,u,w); 81 } 82 FindHeavyEdge(1,0,0); 83 ConnectHeavyEdge(1,1); 84 memset(tree,0,sizeof tree); 85 for(int i = 0; i < tot; i += 2){ 86 u = e[i].to; 87 v = e[i+1].to; 88 if(dep[u] < dep[v]) swap(u,v); 89 update(0,clk-1,loc[u],e[i].w,1); 90 } 91 while(m--){ 92 scanf("%d%d%d",&op,&u,&v); 93 if(op) printf("%d ",solve(u,v)); 94 else{ 95 int ith = (u-1)*2; 96 if(dep[e[ith].to] < dep[e[ith+1].to]) ++ith; 97 update(0,clk-1,loc[e[ith].to],v,1); 98 } 99 } 100 } 101 return 0; 102 }