洛谷P3366 【模板】最小生成树(LCT)
【模板】最小生成树
解题思路
用LCT来维护最小生成树。
除了把各顶点作为节点外,每条边也都视为一个节点。对于要加入的边\(e\),检查其两顶点\(x\)和\(y\)是否在同一棵树中,如果不在,则让\(e\)连接\(x\)和\(y\)如果在一棵树中,则找到\(x\)到\(y\)的路径上最长的边,与\(e\)比较,如果\(e\)更小,则删掉那条边,再把\(e\)加入。只要维护一下最长的边的编号即可。
代码如下
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 300005;
int fa[N], ch[N][2], sta[N], maxx[N];
ll v[N];
bool rev[N];
inline bool get(int x)
{
return ch[fa[x]][1] == x;
}
inline bool is_root(int x)
{
return (!fa[x] || ch[fa[x]][1] != x && ch[fa[x]][0] != x);
}
inline void pushr(int x)
{
swap(ch[x][0], ch[x][1]);
rev[x] ^= 1;
}
inline void push_up(int x)
{
int t = v[maxx[ch[x][1]]] > v[maxx[ch[x][0]]]? maxx[ch[x][1]]: maxx[ch[x][0]];
maxx[x] = v[t] > v[x]? t: x;
}
inline void push_down(int x)
{
if(rev[x]){
pushr(ch[x][0]);
pushr(ch[x][1]);
rev[x] = 0;
}
}
inline void rotate(int x)
{
int y = fa[x], z = fa[y];
int u = get(x);
ch[y][u] = ch[x][u^1], fa[ch[x][u^1]] = y;
if(!is_root(y))
ch[z][get(y)] = x;
fa[x] = z;
ch[x][u^1] = y, fa[y] = x;
push_up(y), push_up(x);
}
inline void splay(int x)
{
int pos = 0;
sta[++pos] = x;
for(int i = x; !is_root(i); i = fa[i])
sta[++pos] = fa[i];
while(pos)
push_down(sta[pos--]);
while(!is_root(x)){
int y = fa[x];
if(!is_root(y))
get(x) == get(y)? rotate(y): rotate(x);
rotate(x);
}
}
inline void access(int x)
{
for(int y = 0; x; y = x, x = fa[x])
splay(x), ch[x][1] = y, push_up(x);
}
inline void make_root(int x)
{
access(x);splay(x);
pushr(x);
}
inline void split(int x, int y)
{
make_root(x);
access(y);splay(y);
}
inline int find_root(int x)
{
access(x);splay(x);
while(ch[x][0]){
push_down(x);
x = ch[x][0];
}
splay(x);
return x;
}
int a[N], b[N];
void link(int id)
{
make_root(a[id]);
make_root(b[id]);
fa[a[id]] = id;
fa[b[id]] = id;
}
int main()
{
int n, m;
scanf("%d%d", &n, &m);
int line = 0;
ll sum = 0;
for(int i = n + 1; i <= n + m; i ++){
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
a[i] = x, b[i] = y, v[i] = z;
maxx[i] = i;
make_root(x);
if(find_root(y) != x){
link(i);
++line;
sum += z;
}
else {
split(x, y);
int k = maxx[y];
if(v[k] > z){
splay(k);
fa[ch[k][0]] = fa[ch[k][1]] = 0;
ch[k][0] = ch[k][1] = 0;
link(i);
sum -= v[k] - z;
}
}
}
if(line == n - 1)
printf("%lld\n", sum);
else
printf("orz\n");
return 0;
}
洛谷P3366 【模板】最小生成树(LCT)的更多相关文章
- [洛谷P3366] [模板] 最小生成树
存个模板,顺便复习一下kruskal和prim. 题目传送门 kruskal 稀疏图上表现更优. 设点数为n,边数为m. 复杂度:O(mlogm). 先对所有边按照边权排序,初始化并查集的信息. 然后 ...
- 最小生成树 & 洛谷P3366【模板】最小生成树 & 洛谷P2820 局域网
嗯... 理解生成树的概念: 在一幅图中将所有n个点连接起来的n-1条边所形成的树. 最小生成树: 边权之和最小的生成树. 最小瓶颈生成树: 对于带权图,最大权值最小的生成树. 如何操作? 1.Pri ...
- 洛谷P3366【模板】最小生成树-克鲁斯卡尔Kruskal算法详解附赠习题
链接 题目描述 如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz 输入输出格式 输入格式: 第一行包含两个整数N.M,表示该图共有N个结点和M条无向边.(N<=5000,M&l ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)
为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...
- 洛谷P3375 [模板]KMP字符串匹配
To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果 ...
- 【AC自动机】洛谷三道模板题
[题目链接] https://www.luogu.org/problem/P3808 [题意] 给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过. [题解] 不再介绍基础知识了,就是裸的模 ...
- 洛谷-P5357-【模板】AC自动机(二次加强版)
题目传送门 -------------------------------------- 过年在家无聊补一下这周做的几道AC自动机的模板题 sol:AC自动机,还是要解决跳fail边产生的重复访问,但 ...
- 洛谷.1919.[模板]A*B Problem升级版(FFT)
题目链接:洛谷.BZOJ2179 //将乘数拆成 a0*10^n + a1*10^(n-1) + ... + a_n-1的形式 //可以发现多项式乘法就模拟了竖式乘法 所以用FFT即可 注意处理进位 ...
- 洛谷.3803.[模板]多项式乘法(FFT)
题目链接:洛谷.LOJ. FFT相关:快速傅里叶变换(FFT)详解.FFT总结.从多项式乘法到快速傅里叶变换. 5.4 又看了一遍,这个也不错. 2019.3.7 叕看了一遍,推荐这个. #inclu ...
随机推荐
- CSS的置换和非置换元素
一个来自面试的坑. 面试的时候考官先问了行内元素和块级元素的区别,这个不难理解.然后一脚就踩进了,置换元素的坑.例如img就是行内置换元素,这种行内元素是可以设置宽高的. 什么是置换元素 一个内容不受 ...
- 查找idt table 所對應的page table in Linux
#include <linux/kernel.h> #include <linux/module.h> #include <linux/types.h> #incl ...
- qt 如何使用私有类?
在模块后面加上 -private 关键字,例如 widgets-private 然后 qmake 让配置文件运行一下. 在使用 QStackedLayout 布局并设置 QStackedLayout: ...
- Codeforces 1012B Chemical table (思维+二分图)
<题目链接> 题目大意:给定一个n*m的矩阵网格,向其中加点,对于一个组成矩形的四个点中如果有三个点中有元素,那么第四个点中会自动产生新的元素.问你最少再加多少个点能够填满这个网格.解题分 ...
- JQuery的链式编程与隐式迭代
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 缓存模块redis
1.安装 安装 下载 :wget http://download.redis.io/releases/redis-3.2.8.tar.gz 解压:tar xzf redis-3.2.8.tar.gz ...
- C#设计模式:策略者模式(Stragety Pattern)
一,什么是策略模式? 1,针对同一命令或行为,不同的策略做不同的动作. 2,比如针对一组算法,将每个算法封装到具有公共接口的独立的类中,从而使它们可以相互替换.策略模式使得算法可以在不影响到客户端的情 ...
- 在iOS中去掉input的光标
在input上添加 readonly unselectable="on" οnfοcus="this.blur()" 就可以了.
- RabbitMQ ——消息属性Properties
简介 发送消息可以为消息指定一些参数 Delivery mode: 是否持久化,1 - Non-persistent,2 - Persistent Headers:Headers can have a ...
- NHibernet 事务 修改操作,事务没提交,数据库数据却同步(修改)了
Nhibernet 缓存 由于查询出来的数据和缓存关联,更新之后就算事务没执行提交操作,数据库依旧会更新,解决方法, 清空缓存,实例不和缓存关联,如下面标红代码 public bool UpdateT ...