SDOJ 3740 Graph
Posted kylara
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
以下正解
对于询问(u,v),分为两种情况
每个点记录第一次的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 */
以上是关于SDOJ 3740 Graph的主要内容,如果未能解决你的问题,请参考以下文章