因为边很少,我们可以把非树边单独判断。
然后每个点相邻的点,其实就是一个BFS序。最后把非树边单独求一下。
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include
//#define int long long
using namespace std;
const int N=1e5+10;
int n,st[N],ed[N],dfn[N],m,f[N],cnt,w[N],sum[N<<2],fa[N];
vector<int> g[N],v[N];
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
void bfs(){
queue<int> q; q.push(1); cnt=0; dfn[1]=++cnt;
while(q.size()){
int u=q.front(); q.pop();
for(int to:g[u]) if(!dfn[to]){
dfn[to]=++cnt; fa[to]=u;
if(!st[u]) st[u]=dfn[to];
ed[u]=max(ed[u],dfn[to]);
q.push(to);
}
}
}
#define mid (l+r>>1)
void change(int p,int l,int r,int x,int v){
if(l==r){sum[p]+=v; return ;}
if(x<=mid) change(p<<1,l,mid,x,v);
else change(p<<1|1,mid+1,r,x,v);
sum[p]=sum[p<<1]+sum[p<<1|1];
}
int ask(int p,int l,int r,int ql,int qr){
if(l==ql&&r==qr) return sum[p];
if(qr<=mid) return ask(p<<1,l,mid,ql,qr);
else if(ql>mid) return ask(p<<1|1,mid+1,r,ql,qr);
else return ask(p<<1,l,mid,ql,mid)+ask(p<<1|1,mid+1,r,mid+1,qr);
}
int calc(int x){
int res=w[fa[x]];
if(st[x]) res+=ask(1,1,n,st[x],ed[x]);
for(int to:v[x]) res+=w[to];
return res;
}
void solve(){
cin>>n>>m; memset(sum,0,sizeof sum);
assert(m>=n-1);
for(int i=1;i<=n;i++)
g[i].clear(),v[i].clear(),f[i]=i,st[i]=ed[i]=dfn[i]=w[i]=fa[i]=0;
for(int i=1,a,b;i<=m;i++){
scanf("%d %d",&a,&b);
int x=find(a),y=find(b);
if(x!=y) g[a].push_back(b),g[b].push_back(a),f[x]=y;
else v[a].push_back(b),v[b].push_back(a);
}
bfs(); int q; cin>>q;
for(int i=1,op,x,y;i<=q;i++){
scanf("%d %d",&op,&x);
if(!op) scanf("%d",&y),w[x]+=y,change(1,1,n,dfn[x],y);
else printf("%d\n",calc(x));
}
}
signed main(){
int T; cin>>T; while(T--) solve();
return 0;
}