概述
题目链接
思路:n个点n条边必定有一个环,那么在加边的时候判断一下如果当前加的边会构成环,就吧这条边断开,其中一个端点换成n+1,那么就形成了一个n+1个点n条边的树,然后裸的树链剖分,答案取三种情况的最小值就好,具体看代码~
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int n,m,vis[maxn];
///**树链剖分
int tot,num;
int head[maxn],fa[maxn],deep[maxn],son[maxn],sz[maxn],top[maxn],id[maxn];
int val[maxn];///点权
struct E{int to,next,val;}edge[maxn*2];
struct P{int u,v,val;}e[maxn];
void add_edge(int u,int v)
{
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
}
void init()
{
num=tot=0;
for(int i=1;i<=n+1;i++) head[i]=-1,vis[i]=0;
}
void dfs1(int u,int f,int dep)
{
fa[u]=f;deep[u]=dep;
son[u]=0;sz[u]=1;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(v==f) continue;
dfs1(v,u,dep+1);
sz[u]+=sz[v];
if(sz[v]>sz[son[u]]) son[u]=v;
}
}
void dfs2(int u,int tp)
{
id[u]=++num;
top[u]=tp;
if(son[u]) dfs2(son[u],tp);
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(v==son[u]||v==fa[u]) continue;
dfs2(v,v);
}
}
///线段树部分
#define ls rt<<1
#define rs rt<<1|1
#define ll t[rt].l
#define rr t[rt].r
#define LL long long
struct node
{
int l,r;
LL val;
}t[maxn*4];
void pushup(int rt)
{
t[rt].val=t[ls].val+t[rs].val;
}
void build(int rt,int l,int r)
{
t[rt].l=l;
t[rt].r=r;
if(l==r){
t[rt].val=(LL)val[l];
return ;
}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(rt);
}
void update(int rt,int pos,int val)
{
if(ll==rr){
t[rt].val=(LL)val;
return ;
}
int mid=(ll+rr)>>1;
if(pos<=mid) update(ls,pos,val);
else update(rs,pos,val);
pushup(rt);
}
LL query(int rt,int l,int r)
{
if(l<=ll&&rr<=r) return t[rt].val;
int mid=(ll+rr)>>1;
LL ans=0;
if(l<=mid) ans+=query(ls,l,r);
if(r>mid) ans+=query(rs,l,r);
return ans;
}
///
LL solve(int u,int v)
{
int tp1=top[u],tp2=top[v];
LL ans=0;
while(tp1!=tp2){
if(deep[tp1]<deep[tp2]) swap(u,v),swap(tp1,tp2);
ans+=query(1,id[tp1],id[u]);
u=fa[tp1];
tp1=top[u];
}
if(u==v) return ans;
if(deep[u]>deep[v]) swap(u,v);
ans+=query(1,id[son[u]],id[v]);
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
init();
int tx,ty=n+1;
for(int i=1;i<=n;i++){
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].val);
if(vis[e[i].u]&&vis[e[i].v]){
tx=e[i].u;
e[i].u=n+1;
}
vis[e[i].u]=vis[e[i].v]=1;
add_edge(e[i].u,e[i].v);
add_edge(e[i].v,e[i].u);
}
dfs1(1,0,0);
dfs2(1,1);
for(int i=1;i<=n;i++){
if(deep[e[i].u]<deep[e[i].v]) swap(e[i].u,e[i].v);
val[id[e[i].u]]=e[i].val;
}
build(1,1,num);
int op,u,v;
while(m--){
scanf("%d%d%d",&op,&u,&v);
if(op==0) update(1,id[e[u].u],v);
else printf("%lldn",min(solve(u,v),min(solve(u,tx)+solve(v,ty),solve(u,ty)+solve(v,tx))));
}
}
return 0;
}
最后
以上就是酷酷鸵鸟为你收集整理的HDU--6393--Traffic Network in Numazu (树链剖分)的全部内容,希望文章能够帮你解决HDU--6393--Traffic Network in Numazu (树链剖分)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复