题目描述

给出一个N个点M条边的无向带权图,以及Q个询问,每次询问在图中删掉一条边后图的最小生成树。(各询问间独立,每次询问不对之后的询问产生影响,即被删掉的边在下一条询问中依然存在)

输入

第一行两个正整数N,M(N<=50000,M<=100000)表示原图的顶点数和边数。
下面M行,每行三个整数X,Y,W描述了图的一条边(X,Y),其边权为W(W<=10000)。保证两点之间至多只有一条边。
接着一行一个正整数Q,表示询问数。(1<=Q<=100000)
下面Q行,每行一个询问,询问中包含一个正整数T,表示把编号为T的边删掉(边从1到M按输入顺序编号)。

输出

Q行,对于每个询问输出对应最小生成树的边权和的值,如果图不连通则输出“Not connected”

样例输入

4 4
1 2 3
1 3 5
2 3 9
2 4 1
4
1
2
3
4

样例输出

15
13
9
Not connected


题解

最小生成树+树链剖分+线段树

首先考虑,不在最小生成树上的边,去掉后都可以选择最小生成树。

然后如果删掉在最小生成树上的边,那么去掉后,原有的树边一定不变,新添加的一定是能够构成一棵树的非树边。

于是先求出最小生成树,然后看每条非树边能够使多少条树边删去后连通。显然是树链上的边。

所以可以使用树链剖分+线段树的方法实现:使一条链上所有边权值对某值取min、查询某条边的权值。此时需要把边权放到深度更大的那个端点的点权上。

时间复杂度$O(n\log^2n)$,代码中使用了永久化标记。

注意:如果原图就是不连通的,那么每个询问的结果都应是“Not connected”。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 50010
#define lson l , mid , x << 1
#define rson mid + 1 , r , x << 1 | 1
using namespace std;
struct data
{
int x , y , z , id;
bool vis;
}a[N << 1];
int f[N] , head[N] , to[N << 1] , val[N << 1] , next[N << 1] , cnt , ref[N << 1] , fa[N] , deep[N] , si[N] , bl[N] , pos[N] , tot , mn[N << 2] , n;
bool cmp1(const data &a , const data &b)
{
return a.z < b.z;
}
bool cmp2(const data &a , const data &b)
{
return a.id < b.id;
}
int find(int x)
{
return x == f[x] ? x : f[x] = find(f[x]);
}
void add(int x , int y , int z)
{
to[++cnt] = y , val[cnt] = z , next[cnt] = head[x] , head[x] = cnt;
}
void dfs1(int x)
{
int i;
si[x] = 1;
for(i = head[x] ; i ; i = next[i])
if(to[i] != fa[x])
fa[to[i]] = x , deep[to[i]] = deep[x] + 1 , ref[val[i]] = to[i] , dfs1(to[i]) , si[x] += si[to[i]];
}
void dfs2(int x , int c)
{
int i , k = 0;
bl[x] = c , pos[x] = ++tot;
for(i = head[x] ; i ; i = next[i])
if(to[i] != fa[x] && si[to[i]] > si[k])
k = to[i];
if(k)
{
dfs2(k , c);
for(i = head[x] ; i ; i = next[i])
if(to[i] != fa[x] && to[i] != k)
dfs2(to[i] , to[i]);
}
}
void update(int b , int e , int a , int l , int r , int x)
{
if(b <= l && r <= e)
{
mn[x] = min(mn[x] , a);
return;
}
int mid = (l + r) >> 1;
if(b <= mid) update(b , e , a , lson);
if(e > mid) update(b , e , a , rson);
}
int query(int p , int l , int r , int x)
{
if(l == r) return mn[x];
int mid = (l + r) >> 1;
if(p <= mid) return min(mn[x] , query(p , lson));
else return min(mn[x] , query(p , rson));
}
void modify(int x , int y , int v)
{
while(bl[x] != bl[y])
{
if(deep[bl[x]] < deep[bl[y]]) swap(x , y);
update(pos[bl[x]] , pos[x] , v , 1 , n , 1) , x = fa[bl[x]];
}
if(deep[x] > deep[y]) swap(x , y);
if(x != y) update(pos[x] + 1 , pos[y] , v , 1 , n , 1);
}
int main()
{
int m , q , i , sum = 0 , x , v , c = 0;
scanf("%d%d" , &n , &m);
for(i = 1 ; i <= m ; i ++ ) scanf("%d%d%d" , &a[i].x , &a[i].y , &a[i].z) , a[i].id = i;
sort(a + 1 , a + m + 1 , cmp1);
for(i = 1 ; i <= n ; i ++ ) f[i] = i;
for(i = 1 ; i <= m ; i ++ )
if(find(a[i].x) != find(a[i].y))
sum += a[i].z , a[i].vis = 1 , add(a[i].x , a[i].y , a[i].id) , add(a[i].y , a[i].x , a[i].id) , f[f[a[i].x]] = f[a[i].y] , c ++ ;
if(c < n - 1)
{
scanf("%d" , &q);
while(q -- ) puts("Not connected");
return 0;
}
dfs1(1) , dfs2(1 , 1);
memset(mn , 0x3f , sizeof(mn));
sort(a + 1 , a + m + 1 , cmp2);
for(i = 1 ; i <= m ; i ++ )
if(!a[i].vis)
modify(a[i].x , a[i].y , a[i].z);
scanf("%d" , &q);
while(q -- )
{
scanf("%d" , &x);
if(!a[x].vis) printf("%d\n" , sum);
else
{
v = query(pos[ref[x]] , 1 , n , 1);
if(v == 0x3f3f3f3f) puts("Not connected");
else printf("%d\n" , sum - a[x].z + v);
}
}
return 0;
}

【bzoj2238】Mst 最小生成树+树链剖分+线段树的更多相关文章

  1. 【Codeforces827D/CF827D】Best Edge Weight(最小生成树性质+倍增/树链剖分+线段树)

    题目 Codeforces827D 分析 倍增神题--(感谢T*C神犇给我讲qwq) 这道题需要考虑最小生成树的性质.首先随便求出一棵最小生成树,把树边和非树边分开处理. 首先,对于非树边\((u,v ...

  2. [HDU3710] Battle Over Cities [树链剖分+线段树+并查集+kruskal+思维]

    题面 一句话题意: 给定一张 N 个点, M 条边的无向连通图, 每条边上有边权 w . 求删去任意一个点后的最小生成树的边权之和. 思路 首先肯定要$kruskal$一下 考虑$MST$里面去掉一个 ...

  3. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  4. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  5. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  6. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  7. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  8. HDU4897 (树链剖分+线段树)

    Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...

  9. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

随机推荐

  1. 深入浅出:了解JavaScript中的call,apply,bind的差别

     在 javascript之 this 关键字详解文章中,谈及了如下内容,做一个简单的回顾:         1.this对象的涵义就是指向当前对象中的属性和方法.       2.this指向的可变 ...

  2. 关于使用js下载图片

    使用js进行图片下载是很常见的需求,但是解决起来却不是那么顺利. 服务器返回了一个图片地址,网上一搜基本都是用a标签的download属性,但是兼容性实在是很差.这里推荐使用blob. 上代码: va ...

  3. Delphi的Edit控件中只能输入数字且只能输入一个小数点

    使用这种功能必须使用 OnKeyPress 事件,该事件是在窗体中获得键盘输入的焦点,并且在用户按键时发生.OnKeyPress 事件中有个重要参数:Key.Key 参数为Char 型,它能够获得用户 ...

  4. jstree 全部选中事件 select_all 使用

    select_all function of jstree not checked node for jstree-open branch of ajax-jstree 很尴尬啊,找了整个百度,360 ...

  5. 【PHP基础】序列化serialize()与反序列化unserialize()

    序列化serialize()与反序列化unserialize(): 序列化serialize():就是将一个变量所代表的 “内存数据”转换为“字符串”的形式,并持久保存在硬盘(写入文件中保存)上的一种 ...

  6. C# 设置窗口大小为不可调、取消最大化、最小化窗口按键

    this.FormBorderStyle = FormBorderStyle.FixedDialog;//设置边框为不可调节 this.MaximizeBox = false; //取消最大化按键 t ...

  7. python——字符串的操作判断

    s为字符串 s.isalnum()  所有字符都是数字或者字母,为真返回 Ture,否则返回 False. s.isalpha()   所有字符都是字母,为真返回 Ture,否则返回 False. s ...

  8. 笔记-python-redis接口

    笔记-python-redis接口 1.      python 与redis接口 redis是redis数据库的python接口包,为python提供的redis的调用接口. 注:文档内容主要基于h ...

  9. IIS发布错误记录

    1.HTTP 错误 500.19 - Internal Server Error 无法访问请求的页面,因为该页的相关配置数据无效. 详细错误信息模块 IIS Web Core 通知 BeginRequ ...

  10. Android面试收集录17 Android进程优先级

    在安卓系统中:当系统内存不足时,Android系统将根据进程的优先级选择杀死一些不太重要的进程,优先级低的先杀死.进程优先级从高到低如下. 前台进程 处于正在与用户交互的activity 与前台act ...