链接: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+;
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<<];
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] = ;
for(int i = head[u];i;i=e[i].next){
int v = e[i].to;
if(v == fa[u]) continue;
dfs1(v,u,deep+);
siz[u] += siz[v];
if(siz[v] > siz[son[u]]||son[u]==-)
son[u] = v;
}
} void dfs2(int u,int t){
top[u] = t;
tid[u] = ++cnt1;
if(son[u] == -) 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<<] + sum[rt<<|];
} 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 = ;
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 = ;
while(fx != fy){
if(dep[fx] < dep[fy]) swap(fx,fy),swap(x,y);
if(fx == ) ans += query(tid[fx]+,tid[x],,n+,);
else ans += query(tid[fx],tid[x],,n+,);
// 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],,n+,);
return ans;
} void init(){
cnt = cnt1 = ;
memset(son,-,sizeof(son));
memset(head,,sizeof(head));
memset(vis,,sizeof(vis));
} int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&q);
init();
int tx,ty = n+;
for(int i = ;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+;
}
vis[a[i].u] = vis[a[i].v] = ;
add(a[i].u,a[i].v);
add(a[i].v,a[i].u);
}
// cout<<"jsjd: "<<tx<<" "<<ty<<endl;
dfs1(,,);
dfs2(,);
for(int i = ;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(,n+,);
// ct(1,n+1,1);cout<<endl;
while(q--){
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op == ) update(tid[a[x].u],y,,n+,);
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\n",min(solve(x,y),min(num,num1)));
}
}
}
return ;
}

最新文章

  1. Android 网络状态检测
  2. 五句话搞定JavaScript作用域
  3. winfrom 文字滚动
  4. java筛选法求素数
  5. ODOO的命令行调用以及config默认值
  6. 利用SQL注入漏洞登录后台的实现方法
  7. 内存溢出与jvm参数配置 ***最爱那水货
  8. javascript_data
  9. [转]js中的字符串函数集和代码片段
  10. hadooop2.6 job pending research
  11. I.MX6 gpio-keys driver hacking
  12. 导出Excel帮助类
  13. 静态方法块 static 以及对象属性&amp;类属性的用法
  14. python实战第一天-pymysql模块并练习
  15. 分布式 基本理论 CAP
  16. [LNOI2014]LCA(树链剖分+线段树)
  17. php 中间件
  18. 用户登录注册(安全)(常规、FB、google、paypal) 实战
  19. Java显式锁学习总结之五:ReentrantReadWriteLock源码分析
  20. 如何扩大重做日志(redolog)文件的大小

热门文章

  1. eclipse 如何引入本地dtd
  2. 深度:Hadoop对Spark五大维度正面比拼报告!
  3. php利用自定义key,对数据加解密的方法
  4. python 3.5下安装pycrypto
  5. EZ 2018 05 20 NOIP2018 模拟赛(十五)
  6. zjoi2018 day1游记
  7. 基于uFUN开发板的心率计(一)DMA方式获取传感器数据
  8. mybatis-高级结果映射之一对一
  9. 【数据库】Mysql中主键的几种表设计组合的实际应用效果
  10. redis持久化策略梳理及主从环境下的策略调整记录