链接:http://acm.hdu.edu.cn/showproblem.php?pid=6393
思路:n个点,n条边,也就是基环树。。因为只有一个环,我们可以把这个环断开,建一个新的点n+1与之相连,然后就按照树链剖分求边权的方法分类讨论下,过不过这条被分开的边,一共有三种情况取值最小的。
实现代码:
#include<bits/stdc++.h> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define ll long long #define mid int m = (l + r) >> 1 const int M = 1e5+10; int cnt,cnt1,head[M],fa[M],dep[M],son[M],siz[M],top[M],tid[M],n,q,vis[M]; ll val[M]; ll sum[M<<2]; struct node{ int to,next; ll val; }e[M]; struct node1{ int u,v; ll val; }a[M]; void add(int u,int v){ e[++cnt].to = v;e[cnt].next = head[u];head[u] = cnt; } void dfs1(int u,int faz,int deep){ dep[u] = deep; fa[u] = faz; siz[u] = 1; for(int i = head[u];i;i=e[i].next){ int v = e[i].to; if(v == fa[u]) continue; dfs1(v,u,deep+1); siz[u] += siz[v]; if(siz[v] > siz[son[u]]||son[u]==-1) son[u] = v; } } void dfs2(int u,int t){ top[u] = t; tid[u] = ++cnt1; if(son[u] == -1) return ; dfs2(son[u],t); for(int i = head[u];i;i=e[i].next){ int v = e[i].to; if(v != fa[u]&&v != son[u]) dfs2(v,v); } } void pushup(int rt){ sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } void build(int l,int r,int rt){ if(l == r){ sum[rt] = val[l]; return ; } mid; build(lson); build(rson); pushup(rt); } void update(int p,ll c,int l,int r,int rt){ if(l == r){ sum[rt] = c; return ; } mid; if(p <= m) update(p,c,lson); else update(p,c,rson); pushup(rt); } ll query(int L,int R,int l,int r,int rt){ if(L <= l&&R >= r) return sum[rt]; mid; ll ret = 0; if(L <= m) ret += query(L,R,lson); if(R > m) ret += query(L,R,rson); return ret; } /*void ct(int l,int r,int rt){ if(l == r){ cout<<sum[rt]<<" "; return ; } mid; ct(lson); ct(rson); }*/ ll solve(int x,int y){ int fx = top[x],fy = top[y]; ll ans = 0; while(fx != fy){ if(dep[fx] < dep[fy]) swap(fx,fy),swap(x,y); if(fx == 1) ans += query(tid[fx]+1,tid[x],1,n+1,1); else ans += query(tid[fx],tid[x],1,n+1,1); // cout<<x<<" "<<fx<<" "<<ans<<endl; x = fa[fx]; fx = top[x]; } if(x == y) return ans; if(dep[x] > dep[y]) swap(x,y); ans += query(tid[son[x]],tid[y],1,n+1,1); return ans; } void init(){ cnt = cnt1 = 0; memset(son,-1,sizeof(son)); memset(head,0,sizeof(head)); memset(vis,0,sizeof(vis)); } int main() { int t; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&q); init(); int tx,ty = n+1; for(int i = 1;i <= n;i ++){ scanf("%d%d%lld",&a[i].u,&a[i].v,&a[i].val); if(vis[a[i].u]&&vis[a[i].v]){ tx = a[i].u; a[i].u = n+1; } vis[a[i].u] = vis[a[i].v] = 1; add(a[i].u,a[i].v); add(a[i].v,a[i].u); } // cout<<"jsjd: "<<tx<<" "<<ty<<endl; dfs1(1,0,1); dfs2(1,1); for(int i = 1;i <= n;i ++){ if(dep[a[i].u] < dep[a[i].v])swap(a[i].u,a[i].v); val[tid[a[i].u]] = a[i].val; } build(1,n+1,1); // ct(1,n+1,1);cout<<endl; while(q--){ int op,x,y; scanf("%d%d%d",&op,&x,&y); if(op == 0) update(tid[a[x].u],y,1,n+1,1); else{ ll num = solve(x,tx)+solve(y,ty); ll num1 = solve(x,ty)+solve(y,tx); //cout<<"num: "<<num<<"num1 : "<<num1<<"solve "<<solve(x,y)<<endl; printf("%lld ",min(solve(x,y),min(num,num1))); } } } return 0; }