Chika is elected mayor of Numazu. She needs to manage the traffic in this city. To manage the traffic is too hard for her. So she needs your help. You are given the map of the city —— an undirected connected weighted graph with N nodes and N edges, and you have to finish Q missions. Each mission consists of 3 integers OP, X and Y. When OP=0, you need to modify the weight of the Xth edge to Y. When OP=1, you need to calculate the length of the shortest path from node X to node Y.html
The first line contains a single integer T, the number of test cases. Each test case starts with a line containing two integers N and Q, the number of nodes (and edges) and the number of queries. (3≤N≤105)(1≤Q≤105) Each of the following N lines contain the description of the edges. The ith line represents the ith edge, which contains 3 space-separated integers ui, vi, and wi. This means that there is an undirected edge between nodes ui and vi, with a weight of wi. (1≤ui,vi≤N)(1≤wi≤105) Then Q lines follow, the ith line contains 3 integers OP, X and Y. The meaning has been described above.(0≤OP≤1)(1≤X≤105)(1≤Y≤105) It is guaranteed that the graph contains no self loops or multiple edges.node
For each test case, and for each mission whose OP=1, print one line containing one integer, the length of the shortest path between X and Y.c++
2 5 5 1 2 3 2 3 5 2 4 5 2 5 1 4 3 3 0 1 5 1 3 2 1 5 4 0 5 4 1 5 1 5 3 1 2 3 1 3 2 3 4 4 4 5 5 2 5 5 0 1 3 0 4 1 1 1 4數組
5 6 6 6oop
N個點 可是有N條邊 因此必定成環
簡單地講就是樹上在加一條邊
處理上分爲樹的處理和環的處理ui
本題先用並查集維護,找到那個環,將環中的任意一條邊去掉 就成爲樹了。樹能夠用LCA+樹狀數組&樹上差分處理,環就直接特判就行了。三條路,一個是隻走樹,一個是走到X再到Y再到v,一個是走到Y再到X再到u。spa
求最近公共祖先的模板code
//+ DFS void dfs(ll u,ll fa){//dfs建樹 dep[u]=dep[fa]+1; f[u][0]=fa;//初始化每一個點的父節點 L[u]=++dfs_clock; for(int i=head[u];i;i=e[i].next){ int v=e[i].v; if(v!=fa){ G[e[i].id]=v; dfs(v,u); } } R[u]=dfs_clock; } //+ 初始化 void rmq_init(int n) { for(int j=1;j<=19;j++) for(int i=1;i<=n;i++) if(f[i][j-1]) f[i][j] = f[f[i][j-1]][j-1]; } //+ lca&rmq int lca(int u,int v) { if(dep[u]<dep[v]) swap(u,v);//深度深的先處理 for(int i=19;i>=0;i--){ if(dep[u]>=dep[v]+(1<<i)){ u = f[u][i]; } } if(u==v){//跳到同一深度判斷是否完成 return u; } for(int i=19;i>=0;i--){//一塊兒跳 if(f[u][i]!=f[v][i]){ u=f[u][i]; v=f[v][i]; } } return f[u][0]; }
dfs_clock 顧名思義就是遍歷到該點的時間。
R[ ]記錄着訪問該點的時間點 L[ ]記錄着該點最深的子節點的時間點。這樣處理利於樹狀數組。htm
修改時支持對該區間前綴和的修改
前綴和已經維護好了 因此兩點最短距離就是兩點的前綴和的和減去2倍的父節點的前綴和
#include<bits/stdc++.h> using namespace std; #define maxn 100005 typedef long long ll; struct Edge{ int v,next,id; }e[maxn<<1]; int n,a[maxn],head[maxn],dep[maxn<<1],cnt,pos[maxn],dfs_seq[maxn<<1],dfn,f[maxn<<1][20]; int L[maxn],R[maxn],dfs_clock,G[maxn]; ll W[maxn],C[maxn]; inline void add(int u,int v,int id){ cnt++; e[cnt].v=v; e[cnt].next=head[u]; e[cnt].id=id; head[u]=cnt; } inline int lowbit(int x){return (x)&(-x);} void init(){ memset(head,0,sizeof(head)); memset(C,0,sizeof(C)); memset(dep,0,sizeof(dep)); cnt=0; dfs_clock=0; } void dfs(ll u,ll fa){//dfs建樹 dep[u]=dep[fa]+1; f[u][0]=fa;//初始化每一個點的父節點 L[u]=++dfs_clock; for(int i=head[u];i;i=e[i].next){ int v=e[i].v; if(v!=fa){ G[e[i].id]=v; dfs(v,u); } } R[u]=dfs_clock; } void rmq_init(int n) { for(int j=1;j<=19;j++) for(int i=1;i<=n;i++) if(f[i][j-1]) f[i][j] = f[f[i][j-1]][j-1]; } int lca(int u,int v) { if(dep[u]<dep[v]) swap(u,v);//深度深的先處理 for(int i=19;i>=0;i--){ if(dep[u]>=dep[v]+(1<<i)){ u = f[u][i]; } } if(u==v){//跳到同一深度判斷是否完成 return u; } for(int i=19;i>=0;i--){//一塊兒跳 if(f[u][i]!=f[v][i]){ u=f[u][i]; v=f[v][i]; } } return f[u][0]; } inline void update(int i,ll x) { for(;i<=n;i+=lowbit(i)) C[i]+=x; } inline ll sum(int i) { ll s=0; for(;i>0;i-=lowbit(i)) s+=C[i]; return s; } inline ll dist(int u,int v) { return sum(L[u])+sum(L[v])-2*sum(L[lca(u,v)]); } int main() { int i,u,v,k,q,T; ll w; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&q); init(); for(i=1;i<=n-1;++i){ scanf("%d%d%lld",&u,&v,&w); add(u,v,i); add(v,u,i); W[i]=w; } dfs(1,0); rmq_init(n); int X,Y; ll Z; scanf("%d%d%lld",&X,&Y,&Z); W[n] = Z; for(i=1;i<n;++i){ update(L[G[i]],W[i]); update(R[G[i]]+1,-W[i]); } while(q--){ scanf("%d",&k); if(k==0){ scanf("%d%lld",&u,&w); if(u==n) W[n] = w; else{ update(L[G[u]],w-W[u]); update(R[G[u]]+1,-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,Y)+Z); ans=min(ans,dist(u,Y)+dist(v,X)+Z); printf("%lld\n",ans); } } } return 0; }