UVA1265 Tour Belt Kruskal重构树、倍增、树上差分
题意:定义$Tour \, Belt$为某张图上的一个满足以下条件的点集:①点集中至少有$2$个点②任意两点互相连通③图上两个端点都在这个点集中的边的权值的最小值严格大于图上只有一个端点在这个点集中的边的权值的最大值。现在给你一张$N$个点,$M$条边的图,请给出这张图上所有$Tour\,Belt$中包含的点数的和。$N \leq 5000 , M \leq \frac{N(N - 1)}{2}$
虽然这道题没有必要用$Kruskal$重构树来写,但是考%你赛的时候写$Kruskal$重构树的时候写挂了(LCA写错了),所以补上这个坑
因为我们需要某个连通块中所有边都大于其连向外面的边,所以考虑使用最大生成树的加边方式,每一次形成一个新的连通块的时候统计一次答案。可是我们不知道这个连通块中是否还有边没有被加进去,无法知道那些没有被加入的边是否会导致这个连通块的贡献变为$0$,所以实现有些麻烦(实际上根据这一点可以写出$O(N^2)$的并查集写法,然而咕咕咕咕咕)
我们自然地想到使用$Kruskal$重构树解决这个问题。在$Kruskal$重构树中,每个非叶子节点对应一个$Kruskal$过程中形成的连通块,而它的贡献就是这个子树中的叶子节点的个数。我们在非叶子节点中额外记录一个合并时的边权。在$Kruskal$重构树建好后,一遍$dfs$建好树上倍增,然后我们就可以考虑非树边对现有的连通块的影响了。
首先我们可以知道,在$Kruskal$重构树上,某条边的影响范围从两个端点的$LCA$开始,而它会使根到$LCA$路径上父亲对应边权大于等于当前边边权的点失去贡献,因为其父亲合并时的边权就是当前连通块中只连一个端点的边中最大的边权。可以知道这在$Kruskal$重构树上是一条链。我们就可以使用树上倍增找到满足这个条件的深度最低的点,通过树上差分对这一条链打上标记,最后遍历整棵树统计答案。
时间复杂度为$O(MlogN)$,理论上过不了实际上跑得飞快???
我的第一棵$Kruskal$重构树qaq
#include<bits/stdc++.h>
#define MAXM 1000010
#define MAXN 5010
using namespace std;
inline int read() {
;
;
char c = getchar();
while(!isdigit(c)) {
if(c == '-')
f = ;
c = getchar();
}
while(isdigit(c)) {
a = (a << ) + (a << ) + (c ^ ');
c = getchar();
}
return f ? -a : a;
}
struct Edge {
int start , end , w;
} Ed[MAXM];
][] , ch[MAXN << ][] , size[MAXN << ] , fa[MAXN << ] , dep[MAXN << ] , tag[MAXN << ] , now[MAXN << ];
int N , M , cntNode , ans;
bool vis[MAXM];
bool cmp(Edge a , Edge b) {
return a.w > b.w;
}
int find(int a) {
return fa[a] == a ? a : (fa[a] = find(fa[a]));
}
void dfs(int now , int fa) {
dep[now] = dep[fa] + ;
to[now][] = fa;
; i <= ; i++)
to[now][i] = to[to[now][i - ]][i - ];
]) {
dfs(ch[now][] , now);
dfs(ch[now][] , now);
}
}
inline int jumpToLCA(int p , int q) {
if(dep[p] < dep[q])
swap(p , q);
; i >= ; i--)
<< i) >= dep[q])
p = to[p][i];
if(p == q)
return p;
; i >= ; i--)
if(to[p][i] != to[q][i]) {
p = to[p][i];
q = to[q][i];
}
];
}
int jump(int n , int w) {
; i >= ; i--)
if(now[to[n][i]] >= w)
n = to[n][i];
return n;
}
int Dfs(int now) {
]) {
]) + Dfs(ch[now][]);
)
ans += size[now];
tag[now] = ;
return t;
}
;
}
int main() {
for(int T = read() ; T ; T--) {
dep[] = ans = ;
memset(vis , , sizeof(vis));
memset(ch , , sizeof(ch));
memset(now , , sizeof(now));
cntNode = N = read();
M = read();
; i <= N ; i++) {
fa[i] = i;
size[i] = ;
}
; i <= M ; i++) {
Ed[i].start = read();
Ed[i].end = read();
Ed[i].w = read();
}
sort(Ed + , Ed + M + , cmp);
; i <= M ; i++) {
int p = find(Ed[i].start) , q = find(Ed[i].end);
if(p != q) {
fa[p] = fa[q] = fa[cntNode] = ++cntNode;
ch[cntNode][] = p;
ch[cntNode][] = q;
size[cntNode] = size[p] + size[q];
now[cntNode] = Ed[i].w;
if(now[p] == Ed[i].w){
tag[p]--;
tag[cntNode]++;
}
if(now[q] == Ed[i].w){
tag[q]--;
tag[cntNode]++;
}
vis[i] = ;
}
}
dfs(cntNode , cntNode);
; i <= M ; i++)
if(!vis[i]) {
int t = jumpToLCA(Ed[i].end , Ed[i].start);
int p = jump(t , Ed[i].w);
tag[t]--;
tag[p]++;
}
Dfs(cntNode);
cout << ans << endl;
}
;
}
题外话:
论把
inline int jumpToLCA(int p , int q) {
if(dep[p] < dep[q])
swap(p , q);
; i >= ; i--)
<< i) >= dep[q])
p = to[p][i];
if(p == q)
return p;
; i >= ; i--)
if(to[p][i] != to[q][i]) {
p = to[p][i];
q = to[q][i];
}
];
}
写成
inline int jumpToLCA(int p , int q) {
if(dep[p] < dep[q])
swap(p , q);
; i >= ; i--)
<< i) >= q)
p = to[p][i];
if(p == q)
return p;
; i >= ; i--)
if(to[p][i] != to[q][i]) {
p = to[p][i];
q = to[q][i];
}
];
}
考%你赛还查不出来qwq
UVA1265 Tour Belt Kruskal重构树、倍增、树上差分的更多相关文章
- BZOJ5415[Noi2018]归程——kruskal重构树+倍增+堆优化dijkstra
题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 n 个节点.m 条边的无向连通图(节点的编号从 1 至 n).我们依次用 l,a 描述一条边的长度.海 ...
- NOI2018Day1T1 归程 并查集 kruskal kruskal重构树 倍增表 Dijkstra
原文链接https://www.cnblogs.com/zhouzhendong/p/NOI2018Day1T1.html 题目传送门 - 洛谷P4768 题意 给定一个无向连通图,有 $n$ 个点 ...
- BZOJ3732Network——kruskal重构树+倍增+LCA/最小生成树+倍增
题目描述 给你N个点的无向图 (1 <= N <= 15,000),记为:1…N. 图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 & ...
- LOJ #2718. 「NOI2018」归程(Dijkstra + Kruskal重构树 + 倍增)
题意 给你一个无向图,其中每条边有两个值 \(l, a\) 代表一条边的长度和海拔. 其中有 \(q\) 次询问(强制在线),每次询问给你两个参数 \(v, p\) ,表示在 \(v\) 出发,能开车 ...
- 【BZOJ 3732】 Network Kruskal重构树+倍增LCA
Kruskal重构树裸题, Sunshine互测的A题就是Kruskal重构树,我通过互测了解到了这个神奇的东西... 理解起来应该没什么难度吧,但是我的Peaks连WA,,, 省选估计要滚粗了TwT ...
- LOJ.2718.[NOI2018]归程(Kruskal重构树 倍增)
LOJ2718 BZOJ5415 洛谷P4768 Rank3+Rank1无压力 BZOJ最初还不是一道权限题... Update 2019.1.5 UOJ上被hack了....好像是纯一条链的数据过不 ...
- BZOJ 4242: 水壶(Kruskal重构树 + Bfs)
题意 一块 \(h ∗ w\) 的区域,存在障碍.空地.\(n\) 个建筑,从一个建筑到另一个建筑的花费为:路径上最长的连续空地的长度. \(q\) 次询问:从建筑 \(s_i\) 到 \(t_i\) ...
- [luogu4768] [NOI2018] 归程 (Dijkstra+Kruskal重构树)
[luogu4768] [NOI2018] 归程 (Dijkstra+Kruskal重构树) 题面 题面较长,这里就不贴了 分析 看到不能经过有积水的边,即不能经过边权小于一定值的边,我们想到了kru ...
- Luogu P4768 [NOI2018]归程(Dijkstra+Kruskal重构树)
P4768 [NOI2018]归程 题面 题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 \(n\) 个节点. \(m\) 条边的无向连通图(节点的编 ...
随机推荐
- loadrunner 场景设计-目标场景设计
场景设计-目标场景设计 by:授客 QQ:1033553122 A. 概述 Goals Types for Goal-Oriented Scenarios 在以目标为向导的场景中,定义你想实现的测 ...
- Fiddler抓包使用教程-模拟低速网络环境
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/73467267 本文出自[赵彦军的博客] 在无线测试中,网络测试是必不可少的环节,通 ...
- Linux小技巧之:两种方法统计访问web网站的前10个IP
获得访问前10位的IP地址: 10.46.170.7 218.202.70.147 77.72.83.87 5.39.217.107 185.197.74.234 185.197.74.231 第二种 ...
- 18LaTeX学习系列之---LaTeX的参考文献
目录 目录 前言 (一)简单的参考文献 1.说明 2.源代码 3.输出效果 (二)以文件管理的方式 1.说明: 2.源代码: 3.输出效果 (三)直接从源网站获取 1.说明 2.操作 目录 本系列是有 ...
- 09LaTeX学习系列之---Latex 字体的设置
目录 目录: (一) 字体族的设置 1.说明: 2.源代码: 3.输出结果: (二) 字体系列的设置 1.源代码: 2.输出效果: (三) 字体形状的设置 1.源代码: 2.输出效果: (四) 字体大 ...
- ccf-20171203 Crontab问题
这题有如下几个点要注意: 1.最开始输出的开始时间和截止时间,这里是不包含截止时间的. 2.月份和星期的英文表示是大小写任意的,并未规定必须是Sat这种形式. 3.星期天的数字标识是0. 我的思路是, ...
- C# 连接Oracle时报错的问题
“/”应用程序中的服务器错误. 试图加载格式不正确的程序. (异常来自 HRESULT:0x8007000B) 说明: 执行当前 Web 请求期间,出现未经处理的异常.请检查堆栈跟踪信息,以了解有关该 ...
- Linux 小知识翻译 - 「模块」
说起module(模块),有的像「可热插拔的零部件」的意思. 在讨论Linux时提到的模块一般是指可以组装到内核中的模块. 模块这个概念是在硬件和程序设计领域中广泛使用的概念.我们这次说的模块特指Li ...
- Beta冲刺! Day1 - 磨刀
Beta冲刺! Day1 - 磨刀 今日已完成 晨瑶:罗列Beta计划.和新人交接.任务安排 昭锡:无 永盛:服务器出现一些 mysql 的问题,伟鹏的爬取脚本没办法远程链接到服务器,在修 立强:学习 ...
- [项目实践] python文件路径引用的规则,记一次使用sys.path[0]的问题,及如何区分 ../与 ./的使用场景
下面是一个获取配置的代码 def getValue(self,section,option): """ @file: string,the name of the con ...