这道题相当于将这两题结合:

  http://poj.org/problem?id=2763

  http://codeforces.com/gym/101808/problem/K

题意:有N各点N条边的带权无向图(相当于一棵树多了一条边),两种操作:修改一条边的权值;求两点间的最短路径。

分析:将任意一条边取出来,其余n-1条边可以结合LCA解最短路。询问时,比较通过取出的边和仅通过树上的边的路径的大小,最小值就是两点的最短路径。

树状数组差分维护点到根节点的距离,根据dfs序来记录需要维护的范围。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define maxn 100005
typedef long long LL;
struct Edge{
int to,next,id;
}edge[maxn<<]; int n,a[maxn],head[maxn],dep[maxn<<],cnt,pos[maxn],dfs_seq[maxn<<],dfn,f[maxn<<][];
int L[maxn],R[maxn],dfs_clock,G[maxn];
LL W[maxn],C[maxn]; inline void add(int u,int v,int id){
edge[cnt].to=v;
edge[cnt].next=head[u];
edge[cnt].id=id;
head[u]=cnt++;
} inline int lowbit(int x){return (x)&(-x);} void init(){
memset(head,-,sizeof(head));
memset(pos,-,sizeof(pos));
memset(C,,sizeof(C));
cnt=dfn=;
dfs_clock=;
} void dfs(int u,int deep)
{
dfs_seq[dfn]=u,dep[dfn]=deep,pos[u]=dfn++;
L[u]=++dfs_clock;
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
if(pos[v]==-){
G[edge[i].id]=v; //important
dfs(v,deep+);
dfs_seq[dfn]=u,dep[dfn++]=deep;
}
}
R[u]=dfs_clock;
} void init_RMQ(int n)
{
for(int i=;i<=n;++i) f[i][]=i;
for(int j=;(<<j)<=n;++j)
for(int i=;i+(<<j)-<=n;++i){
if(dep[f[i][j-]]<dep[f[i+(<<(j-))][j-]]) f[i][j]=f[i][j-];
else f[i][j]=f[i+(<<(j-))][j-];
}
} inline int RMQ(int L,int R)
{
int k=;
while(<<(k+)<=R-L+) ++k;
if(dep[f[L][k]]<dep[f[R-(<<k)+][k]]) return f[L][k];
return f[R-(<<k)+][k];
} inline int lca(int u,int v)
{
if(pos[u]>pos[v]) return dfs_seq[RMQ(pos[v],pos[u])];
return dfs_seq[RMQ(pos[u],pos[v])];
} inline void update(int i,LL x)
{
for(;i<=n;i+=lowbit(i)) C[i]+=x;
} inline LL sum(int i)
{
LL s=;
for(;i>;i-=lowbit(i)) s+=C[i];
return s;
} inline LL dist(int u,int v)
{
return sum(L[u])+sum(L[v])-*sum(L[lca(u,v)]);
} int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int i,u,v,k,q,s,T;
LL w;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&q);
init();
for(i=;i<=n-;++i){
scanf("%d%d%lld",&u,&v,&w);
add(u,v,i);
add(v,u,i);
W[i]=w;
}
dfs(,);
init_RMQ(dfn-);
int X,Y; LL Z;
scanf("%d%d%lld",&X,&Y,&Z); //第n条边
W[n] = Z;
for(i=;i<n;++i){
update(L[G[i]],W[i]);
update(R[G[i]]+,-W[i]);
} while(q--){
scanf("%d",&k);
if(k==){
scanf("%d%lld",&u,&w);
if(u==n)
W[n] = w;
else{
update(L[G[u]],w-W[u]);
update(R[G[u]]+,-w+W[u]);
W[u]=w;
}
}
else{
scanf("%d%d",&u,&v);
LL ans=dist(u,v);
ans=min(ans,dist(u,X)+dist(v,X));
ans=min(ans,dist(u,Y)+dist(v,Y));
ans=min(ans,dist(u,X)+dist(v,Y)+Z);
ans=min(ans,dist(u,Y)+dist(v,X)+Z);
printf("%lld\n",ans);
}
}
}
return ;
}

最新文章

  1. K型热电耦高精度分段线性拟合(C语言)
  2. C#利用微软库完成设备网络定位(经纬度-地址)
  3. System.StackOverflowException的一个例子(转)
  4. Oracle VM VirtualBox配置文件
  5. /proc/stat文件详解(翻译)
  6. 如何让div中的内容垂直居中
  7. 禁止多行文本框textarea拖拽
  8. ARC内存使用注意事项
  9. Sass编译Css
  10. Linux 教程 技巧集
  11. angular select 遍历使用ng-option绑定的时候下面多出一个空白的option处理方法
  12. RestTemplate的使用介绍汇总
  13. 线段树模板hdu 1754:I Hate It
  14. 13.C# 定义类成员
  15. hdoj:2029
  16. Javascript深入理解构造函数和原型对象
  17. CentOS7系统下YUM安装安装Mongodb 3.4
  18. C#杂乱知识汇总
  19. ubuntu sublime text 3 build 3083 license
  20. python pycurl属性

热门文章

  1. win下如何查看那个网络端口被那个应用程序使用
  2. ApexSql Log 2016破解版&amp;补丁
  3. VUE:使用vue-cli脚手架无法安装npm install axios 的巨坑
  4. Linux初学者学习资料
  5. input file reader
  6. java 遍历String
  7. Vimium、CrxMouse配置信息
  8. EntityFramework增删改查
  9. std::function(3)
  10. ios 时间解析 差8个小时