跑一遍mst。对于非mst上的边,显然删掉不影响。

如果删边在树上,相当于这时剩下两个连通块。可以证明要重新构成mst只需要再加一条连接两个连通块的最小边,不会证,yy一下,因为原来连通块连的边权和已经最小化了,就不要动,如果换用两条以上的边,肯定不会更优。

所以问题就是断掉树边,找最小联通边。可以LCT。`````

这种一颗树断成两截找联通边的题有一个常用思路,要使得联通,必须得有非树边两端点形成的链过这个断边。换句话说,一条非树边两点形成的树上链可以在树断掉后成为联通边当且仅当他经过的边断掉。

这个思路应该在先前这个poj题「闇の連鎖」中出现过,很容易证。其实换句话说这个跟次小生成树做法比较像。

那么只要看经过这个断边的所有非树边中最小的是哪个,用他来联通,总体来看,就是把每条非树边路径上用自己的代价更新一波最小值。

用线段树打标记维护,最后查询的时候直接查单点最小值计算答案即可。

注意判无解。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define dbg(x) cerr << #x << " = " << x <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=1e5+,INF=0x3f3f3f3f;
struct thxorz{int to,nxt,w;}G[N];
int Head[N],tot,used[N];
int n,m,q;
inline void Addedge(int x,int y,int z){
G[++tot].to=y,G[tot].nxt=Head[x],Head[x]=tot,G[tot].w=z;
G[++tot].to=x,G[tot].nxt=Head[y],Head[y]=tot,G[tot].w=z;
}
struct stothx{
int u,v,w,id;
inline bool operator <(const stothx&x)const{return w<x.w;}
}E[N],_E[N];
int anc[N],ans;
int get_anc(int x){return x==anc[x]?x:anc[x]=get_anc(anc[x]);}
int fa[N],topfa[N],son[N],cnt[N],d[N],st[N],tim;
#define y G[j].to
void dfs1(int x,int f){
fa[x]=f,d[x]=d[f]+,cnt[x]=;int tmp=-;
for(register int j=Head[x];j;j=G[j].nxt)if(y^f)dfs1(y,x),cnt[x]+=cnt[y],MAX(tmp,cnt[y])&&(son[x]=y);
}
void dfs2(int x,int topf){
topfa[x]=topf,st[x]=tim++;if(!son[x])return;dfs2(son[x],topf);
for(register int j=Head[x];j;j=G[j].nxt)if(y^fa[x]&&y^son[x])dfs2(y,y);
}
#undef y
#define lc i<<1
#define rc i<<1|1
int minv[N<<],mtag[N<<];
inline void pushup(int i){minv[i]=_min(minv[lc],minv[rc]);}
inline void pushdown(int i){
if(mtag[i]<INF)
MIN(minv[lc],mtag[i]),MIN(minv[rc],mtag[i]),MIN(mtag[lc],mtag[i]),MIN(mtag[rc],mtag[i]),mtag[i]=INF;
}
void Update(int i,int L,int R,int ql,int qr,int val){//dbg(L),dbg(R),dbg(ql),dbg(qr);
if(ql<=L&&qr>=R){MIN(minv[i],val),MIN(mtag[i],val);return;}
int mid=L+R>>;pushdown(i);
if(ql<=mid)Update(lc,L,mid,ql,qr,val);
if(qr>mid)Update(rc,mid+,R,ql,qr,val);
pushup(i);
}
int Query_min(int i,int L,int R,int x){
if(L==R)return minv[i];
int mid=L+R>>;pushdown(i);
return x<=mid?Query_min(lc,L,mid,x):Query_min(rc,mid+,R,x);
}
inline void Tree_update(int x,int y,int z){
while(topfa[x]^topfa[y]){
if(d[topfa[x]]<d[topfa[y]])x^=y^=x^=y;
Update(,,n-,st[topfa[x]],st[x],z),x=fa[topfa[x]];
}
if(d[x]>d[y])x^=y^=x^=y;
if(x^y)Update(,,n-,st[x]+,st[y],z);
}
inline void mst(){
sort(E+,E+m+);int res=;
for(register int i=;i<=n;++i)anc[i]=i;
for(register int i=;i<=m;++i)
if(get_anc(E[i].u)^get_anc(E[i].v)){
anc[get_anc(E[i].v)]=get_anc(E[i].u);
used[E[i].id]=,ans+=E[i].w;++res;
Addedge(E[i].u,E[i].v,E[i].w);
}
if(res<n-){while(q--)puts("Not connected");exit();}
dfs1(,),dfs2(,);
memset(mtag,0x3f,sizeof mtag),memset(minv,0x3f,sizeof minv);
for(register int i=;i<=m;++i){
if(used[i])used[i]=d[_E[i].u]<d[_E[i].v]?_E[i].v:_E[i].u;
else Tree_update(_E[i].u,_E[i].v,_E[i].w);
}
}
int id;
int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
read(n);read(m);
for(register int i=;i<=m;++i)_E[i].u=read(E[i].u),_E[i].v=read(E[i].v),_E[i].w=read(E[i].w),E[i].id=i;
read(q);mst();
while(q--){
read(id);if(!used[id]){printf("%d\n",ans);continue;}
int tmp=Query_min(,,n-,st[used[id]]);
if(tmp<INF)printf("%d\n",ans-_E[id].w+tmp);
else puts("Not connected");
}
return ;
}

反思:注意这个提到的常用思路,即化非树边为树上链的边覆盖问题。

BZOJ2238 Mst[最小生成树+树剖+线段树]的更多相关文章

  1. BZOJ_2238_Mst_树剖+线段树

    BZOJ_2238_Mst_树剖+线段树 Description 给出一个N个点M条边的无向带权图,以及Q个询问,每次询问在图中删掉一条边后图的最小生成树.(各询问间独立,每次询问不对之后的询问产生影 ...

  2. BZOJ_4551_[Tjoi2016&Heoi2016]树_树剖+线段树

    BZOJ_4551_[Tjoi2016&Heoi2016]树_树剖+线段树 Description 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为 ...

  3. BZOJ_2157_旅游_树剖+线段树

    BZOJ_2157_旅游_树剖+线段树 Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但 ...

  4. 【BZOJ5210】最大连通子块和 树剖线段树+动态DP

    [BZOJ5210]最大连通子块和 Description 给出一棵n个点.以1为根的有根树,点有点权.要求支持如下两种操作: M x y:将点x的点权改为y: Q x:求以x为根的子树的最大连通子块 ...

  5. [LNOI2014]LCA(树剖+线段树)

    \(\%\%\% Fading\) 此题是他第一道黑题(我的第一道黑题是蒲公英) 一直不敢开,后来发现是差分一下,将询问离线,树剖+线段树维护即可 \(Code\ Below:\) #include ...

  6. [CF1007D]Ants[2-SAT+树剖+线段树优化建图]

    题意 我们用路径 \((u, v)\) 表示一棵树上从结点 \(u\) 到结点 \(v\) 的最短路径. 给定一棵由 \(n\) 个结点构成的树.你需要用 \(m\) 种不同的颜色为这棵树的树边染色, ...

  7. LOJ#3088. 「GXOI / GZOI2019」旧词(树剖+线段树)

    题面 传送门 题解 先考虑\(k=1\)的情况,我们可以离线处理,从小到大对于每一个\(i\),令\(1\)到\(i\)的路径上每个节点权值增加\(1\),然后对于所有\(x=i\)的询问查一下\(y ...

  8. BZOJ3531-[Sdoi2014]旅行(树剖+线段树动态开点)

    传送门 完了今天才知道原来线段树的动态开点和主席树是不一样的啊 我们先考虑没有宗教信仰的限制,那么就是一个很明显的树剖+线段树,路径查询最大值以及路径和 然后有了宗教信仰的限制该怎么做呢? 先考虑暴力 ...

  9. 【bzoj4699】树上的最短路(树剖+线段树优化建图)

    题意 给你一棵 $n$ 个点 $n-1$ 条边的树,每条边有一个通过时间.此外有 $m$ 个传送条件 $(x_1,y_1,x_2,y_2,c)$,表示从 $x_1$ 到 $x_2$ 的简单路径上的点可 ...

  10. POJ3237 Tree(树剖+线段树+lazy标记)

    You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbe ...

随机推荐

  1. Centos 7 忘记密码的情况下,修改root密码

    应用场景 linux管理员忘记root密码,需要进行找回操作. 注意事项:本文基于centos7.4环境进行操作,由于centos的版本是有差异的,继续之前请确定好版本 操作步骤 一.重启系统,在开机 ...

  2. Ubuntu18.04.3主力开发机使用记录(一)

    现在是2019年12月02日,在公司使用Ubuntu作为开发机器已经有一段时间了 查看主分区创建时间 安装时间8月26 当时周一,一个新的迭代刚刚开始,早上来到公司发现开不了机:Windows报错蓝屏 ...

  3. bootstrap-table服务端分页操作

    由于数据库查询的数据过多,所以采取服务端分页的操作,避免一次性加载的数据量过多,导致页面加载缓慢. 后端数据的封装格式json数据 rows里的数据是当前页的数据,total是总条数: { " ...

  4. 啃掉Hadoop系列笔记(02)-Hadoop运行环境搭建

    一.新增一个普通用户bigdata

  5. 20190507-学习dubbo有感于梁飞

    “作为一名程序员,BAT肯定是大多数人都想进的,仿佛是一种情愫,就像学生时代的我们对清华北大的向往感觉一样.Dubbo团队中,其中主要负责人就是梁飞了,梁飞的经历还是蛮励志的.梁飞,花名虚极, 200 ...

  6. Kubernetes基石-pod容器

    引用三个问题来叙述Kubernetes的pod容器 1.为什么不直接在一个Docker容器中运行所有的应用进程. 2.为什么pod这种容器中要同时运行多个Docker容器(可以只有一个) 3.为什么k ...

  7. G.Colorful String(The Preliminary Contest for ICPC Asia Xuzhou 2019)

    https://nanti.jisuanke.com/t/4 #include <bits/stdc++.h> using namespace std; ,; typedef unsign ...

  8. 牛客 158F 青蛙 (贪心)

    显然存在一个最优解满足所有青蛙在连续的一段, 每次由最左侧青蛙跳向下一格. 然后二分或者双指针即可求出答案. #include <iostream> #include <sstrea ...

  9. Jenkins常用插件介绍

    摘要: 对于中小型运维团队,jenkins作为运维利器,可以解决很多工作中的痛点.基于UI的特性从而让使用者的入门成本很低,基于插件可以具备认证,记录,条件触发以及联动,让运维工程师可以将精力放在业务 ...

  10. JS基础_break和continue

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...