• FZU 2082 过路费


    过路费

    Time Limit: 1000ms
    Memory Limit: 32768KB
    This problem will be judged on FZU. Original ID: 2082
    64-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个操作。

    操作有两种:

    1. 0 a b,表示更新第a条路的过路费为b,$1leq aleq n-1 $。
    2.  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 }
    View Code
  • 相关阅读:
    shell 基础进阶 *金字塔
    shell,awk两种方法写9*9乘法表
    shell脚本判断一个用户是否登录成功
    shell 冒泡算法 解决数组排序问题
    shell 石头剪刀布
    应用shell (ssh)远程链接主机
    nmcli命令使用
    光盘yum源autofs按需挂载
    LVM扩容,删除
    LVM创建
  • 原文地址:https://www.cnblogs.com/crackpotisback/p/4845577.html
Copyright © 2020-2023  润新知