zoukankan      html  css  js  c++  java
  • SDOJ 3740 Graph

    8.9 t3

    【描述】

    给你一个图,一共有 N 个点,2*N-2 条有向边。
    边目录按两部分给出
    1、 开始的 n-1 条边描述了一颗以 1 号点为根的生成树,即每个点都可以由 1 号点

    到达。
    2、 接下来的 N-1 条边,一定是从 i 到 1(2<=i<=N)的有向边,保证每个点都能到

    1
    有 q 次询问:

    1 x w :表示将第x条边的边权修改为w

    2 u v :询问u到v的最短距离

    【输入格式】

    第一行是 2 个整数 N,Q,表示一共 N 个点 Q 次询问 接下来是 N-1 行,每行 3 个整数 U,V,W,表示了前 N-1 条边,u 到 v 的有向边 接下来 N-1 行,每行 3 个整数 U,V,W,描述了每个点到 1 号点的边,V==1 接下来是 Q 行,表示 Q 次修改与询问

    【输出格式】

    若干行,每行回答一次询问

    【输入样例】

    5 9
    1 3 1
    3 2 2
    1 4 3
    3 5 4
    5 1 5
    3 1 6
    2 1 7
    4 1 8
    2 1 1
    2 1 3
    2 3 5
    2 5 2
    1  1 100
    2 1 3
    1 8 30
    2 4 2
    2 2 4

    【输出样例】

    0
    1
    4
    8
    100
    132
    10

    【数据规模】 

    20%数据 没有修改

    30%数据 2<=N,Q<=1000 (其中有 10%数据没有修改)
    100%数据 2<=N,Q<=100 000, 1 <=边权 <= 1000,000

     
    ----------------------------------------------------------------------------------------
     
    这个题首先一看,20%没有修改.....大概可以写个LCA?
    30% Q<=1000.......大概可以打个暴力?
     

    以下正解

    对于询问(u,v),分为两种情况
    1.u为v的祖先,所以dis=dis[u]-dis[v];
    2.u不是v的祖先 则 u 先到达 1 号点再到达 v 点。此时 u 必须先找到回到 1 的最短路(一定是自身直接回到 1 或通过以 u 为根子树的某点回到 1 )。且1号点到v点的路径唯一。
     
    我们先做dfs序 然后对每个点维护一个dist[i],dist[i]=根到节点距离+节点返回根距离

    每个点记录第一次的dfs序st[i], 子树结束的 ed[i],在对于第 2 种情况是 min{dist[i]}-dis[u] + dis[v]
    其中 i 是 u 的子树,dis[u]表示从 1  u的值

    对于修改(x,w),也分为两种情况

    1.当边 u->v 修改为 w,则 st[v]...ed[v] 增加 w- w’,w’表示 u->v 原来的值

    2.当边 u->1 修改为 w:则 st[u]..st[u]增加 w-w’

    当然暴力修改区间值肯定是会挂掉的ovo 怎么办?

    当然是线段树啦

    等一下 还要提一提查错

    写线段树的时候一定要冷静 之前把 ans=min(ans,query(ql,qr,lc));直接没写min的比较....

    以后先查主函数的逻辑和调用有没有问题,不能一直纠缠改算法和数据结构

    还要注意数据范围和long long 与 int之间的选择,不能全部用long long 

    记得开大数组范围!!!

    记得开大数组范围!!!

    记得开大数组范围!!!

    贴一下代码~

      1 #include<queue>
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<cmath>
      5 #define N 400010
      6 using namespace std;
      7 #define LL long long
      8 int st[N],ed[N],rev[N],idfn=0;
      9 LL dist[N];
     10 int x[N],y[N],z[N];
     11 int n,Q;
     12 struct node
     13 {
     14     int u,v,w,nxt;
     15 }e[N*2];
     16 int first[N],cnt;
     17 void ade(int u,int v,int w)
     18 {
     19     e[++cnt].nxt=first[u];first[u]=cnt;
     20     e[cnt].v=v;e[cnt].u=u;e[cnt].w=w;
     21 }
     22 //segment tree
     23 
     24 #define lc (p<<1)
     25 #define rc (p<<1|1)
     26 LL a[N],mn[N*2];
     27 struct Node
     28 {
     29     int l,r; LL lazy;
     30 }T[N*4];
     31 void pushnow(LL p,LL v)
     32 {
     33     T[p].lazy+=v;
     34     mn[p]+=v;
     35     return;
     36 }
     37 void pushdown(LL p,LL m)
     38 {
     39     if(T[p].lazy)
     40     {
     41         T[lc].lazy+=T[p].lazy;
     42         T[rc].lazy+=T[p].lazy;
     43         mn[lc]+=T[p].lazy;
     44         mn[rc]+=T[p].lazy;
     45         T[p].lazy=0;
     46     }
     47 }
     48 void pushup(int  p)
     49 {
     50     mn[p]=min(mn[lc],mn[rc]);
     51 }
     52 void build(int p,int l,int r)//建树
     53 {
     54     T[p].lazy=0;
     55     T[p].l=l;T[p].r=r;
     56     if(l==r)
     57     {
     58         mn[p]=dist[l];
     59         return;
     60     }
     61     int mid=(l+r)>>1;
     62     build(lc,l,mid);
     63     build(rc,mid+1,r);
     64     pushup(p);
     65 }
     66 void update(int ql,int qr,int v,int p)//向上维护 L=ql
     67 {
     68     if(ql>qr) return;
     69     if(ql<=T[p].l&&T[p].r<=qr)
     70     {
     71         pushnow(p,v);//!!!!!!
     72         return;
     73     }
     74     int mid=(T[p].l+T[p].r)>>1;
     75     pushdown(p,T[p].r-T[p].l+1);
     76     if(ql<=mid)
     77         update(ql,qr,v,lc);
     78     if(qr>mid)
     79         update(ql,qr,v,rc);
     80     pushup(p);
     81 }
     82 LL query(int ql,int qr,int p)
     83 {
     84     if(ql<=T[p].l&&qr>=T[p].r) return mn[p];
     85     int mid=(T[p].l+T[p].r)>>1;
     86     pushdown(p,T[p].r-T[p].l+1);
     87     LL ans=0x3f3f3f3f;
     88     if(ql<=mid) ans=min(ans,query(ql,qr,lc));//!!!!
     89     if(qr>mid) ans=min(ans,query(ql,qr,rc));//!!!!
     90     //pushup(p);
     91     return ans;
     92 }
     93 void getdfn(int rt,int fa,long long w)
     94 {
     95     st[rt]=++idfn;
     96     dist[st[rt]]=w+rev[rt];//算dist[i]值
     97     for(int i=first[rt];i;i=e[i].nxt)
     98     {
     99         if(e[i].v==fa) continue;
    100         getdfn(e[i].v,rt, w+e[i].w);
    101     }
    102     ed[rt]=idfn;
    103 }
    104 //LCA
    105 int h[N],dep[N],fa[N][25];
    106 void dfs(int u)
    107 {
    108     for(int i=1;i<=21;i++) fa[u][i]=fa[fa[u][i-1]][i-1];
    109     for(int i=first[u];i;i=e[i].nxt)
    110     {
    111         int v=e[i].v;
    112         if(v!=fa[u][0])
    113         {
    114             fa[v][0]=u;
    115             h[v]=h[u]+1;
    116             dep[v]=dep[u]+1;
    117             dfs(v);
    118         }
    119     }
    120 }
    121 int lca(int u,int v)
    122 {
    123     if(h[u]<h[v]) return lca(v,u);
    124     int i,d=h[u]-h[v];
    125     for(i=0;i<=20;i++)
    126         if((d>>i)&1) u=fa[u][i];
    127     
    128     if(u==v) return u;
    129     for(i=20;i>=0;i--)
    130     {
    131         if(fa[u][i]!=fa[v][i])
    132         {
    133             u=fa[u][i];
    134             v=fa[v][i];
    135         }
    136     }
    137     return fa[u][0];
    138 }
    139 int main()
    140 {
    141     scanf("%d%d",&n,&Q);
    142     for(int i=1;i<=2*(n-1);i++)
    143     {
    144         scanf("%d%d%d",&x[i],&y[i],&z[i]);
    145         if(i<=n-1) ade(x[i],y[i],z[i]);
    146         else rev[x[i]]=z[i];//cout<<2<<endl;
    147     }//cout<<"x"<<endl;
    148     getdfn(1,0,0);
    149     //cout<<"x"<<endl;
    150     dfs(1);
    151     build(1,1,idfn);
    152     int op,a,b,u,v;
    153     for(int i=1;i<=Q;i++)
    154     {
    155         scanf("%d",&op);
    156         if(op==1)
    157         {
    158             scanf("%d%d",&a,&b);
    159             if(a>=n)
    160             {
    161                 update(st[x[a]],st[x[a]],b-rev[x[a]],1);
    162                 rev[x[a]] = b;
    163             }
    164             else
    165             {
    166                 update(st[y[a]],ed[y[a]],b-z[a] ,1);
    167                 z[a]=b;
    168             }
    169         }
    170         if(op==2)
    171         {
    172             scanf("%d%d",&u,&v);
    173             if(lca(u,v)==u)
    174             {
    175                 long long du=query(st[u],st[u],1)-rev[u];
    176                 long long dv=query(st[v],st[v],1)-rev[v];
    177                 printf("%lld
    ", dv - du);
    178             }
    179             else
    180             {
    181                 LL mnDist=query(st[u],ed[u],1)-query(st[u],st[u],1) + rev[u];
    182                 LL dv=query(st[v],st[v],1)-rev[v];
    183                 printf("%lld
    ",mnDist+dv);
    184             }
    185         }
    186     }
    187     return 0;
    188 }/*
    189 5 9
    190 1 3 1
    191 3 2 2
    192 1 4 3
    193 3 5 4
    194 5 1 5
    195 3 1 6
    196 2 1 7
    197 4 1 8
    198 2 1 1
    199 2 1 3
    200 2 3 5
    201 2 5 2
    202 1 1 100
    203 2 1 3
    204 1 8 30
    205 2 4 2
    206 2 2 4
    207 */
    233333
  • 相关阅读:
    Android_Spinner_example
    23.pyspider安装
    22.Windows及linux下gerapy使用
    21.scrapy爬虫部署
    12.利用kakatips对网站数据信息监控
    11.启信宝数据二次筛选解密(字符串的分割与拼接及正则匹配)-2
    10.Ubuntu操作系统及python2.7、3.5 exe
    9.数据库多表一起查询
    8.代理ip使用
    7.阿布云代理服务器试用
  • 原文地址:https://www.cnblogs.com/kylara/p/9447744.html
Copyright © 2011-2022 走看看