由最后一句话可知,这个图为一个环。
那么用树状数组保存每一条边的值,然后每一次询问找u到v的总值就行,然后和取反比较(即总长度减去这个值,就是另一个方向的)。输出比较大的。
更改值也容易。
先处理一下每个点的位置,毕竟1 2 3 4 不一定连接在一起。
我的算法对n=1,n=2会有问题,所以特判一下。
当时时间不够查代码了,说到底还是菜。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
#define LL long long
const int maxn=2e5+55;
int n,m;
int head[maxn],nxt[maxn],to[maxn],sz;
int w[maxn];
struct node
{
int u,v,w;
}len[maxn];
void add(int u,int v,int ww)
{
nxt[sz]=head[u];
to[sz]=v;
w[sz]=ww;
head[u]=sz++;
}
int tm;
int fsn[maxn];
int vis[maxn];
void dfs(int u,int pre)
{
if(fsn[u]) return;
fsn[u]=++tm;
for(int i=head[u];~i;i=nxt[i]){
if(vis[i]) continue;
int v=to[i];
if(tm==n) return;
if(v==pre) continue;
vis[i]=1;
dfs(v,u);
}
}
int sum[maxn];
int lowbit(int x)
{
return x&-x;
}
void addshu(int x,int p)
{
for(int i=x;i<=n;i+=lowbit(i)){
sum[i]+=p;
}
}
int query(int x)
{
int ans=0;
for(int i=x;i>=1;i-=lowbit(i)){
ans+=sum[i];
}
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
sz=0;
tm=0;
int SUM=0;
scanf("%d %d",&n,&m);
memset(vis,0,sizeof vis);
for(int i=1;i<=n;i++) head[i]=-1,sum[i]=0,fsn[i]=0;
for(int i=1;i<=m;i++){
int u,v,ww;scanf("%d %d %d",&u,&v,&ww);
add(u,v,ww);
add(v,u,ww);
len[i].u=u;
len[i].v=v;
len[i].w=ww;
SUM+=ww;
}
dfs(1,-1);
for(int i=1;i<=m;i++){
int u=fsn[len[i].u];
int v=fsn[len[i].v];
if(u>v) swap(v,u);
if(u==1&&v==n)
addshu(1,len[i].w);
else
addshu(v,len[i].w);
len[i].u=u;
len[i].v=v;
}
int q;scanf("%d",&q);
while(q--){
int kind;scanf("%d",&kind);
if(kind==1){
int x,y;scanf("%d %d",&x,&y);
int chang=y-len[x].w;
int u=len[x].u;
int v=len[x].v;
SUM+=chang;
if(u==1&&v==n)
addshu(1,chang);
else
addshu(v,chang);
len[x].w=y;
}else{
int u,v;scanf("%d%d",&u,&v);
u=fsn[u];
v=fsn[v];
if(u>v) swap(u,v);
if(u==v||n==1){
printf("%d\n",SUM);
}else{
if(n==2){
printf("%d\n",max(len[1].w,len[2].w));
continue;
}
int now=query(v)-query(u);
//printf("*%d %d\n",query(v),query(u));
printf("%d\n",max(now,SUM-now));
}
}
}
}
}