https://www.luogu.org/problemnew/show/P2387

考虑先将所有边按 a 值排序,依次加入每一条边,如果这条边的两个端点 ( l, r ) 之间的简单路径中 b 的最大值大于这条边的 b 值,删掉最大的一条边,加入这条边,如果 l 和 r 不连通,则直接 link

需要注意的是将边权转换为点权,将第 i 条边变成编号为 i + n 的点,维护最大值的位置就可以了

这题还有自环( 坑了我半个小时 )

#include <bits/stdc++.h>
using namespace std; typedef unsigned long long ull;
typedef long long ll; template <typename _T>
inline void read(_T &f) {
f = 0; _T fu = 1; char c = getchar();
while(c < '0' || c > '9') {if(c == '-') fu = -1; c = getchar();}
while(c >= '0' && c <= '9') {f = (f << 3) + (f << 1) + (c & 15); c = getchar();}
f *= fu;
} const int N = 150000 + 10; struct ele {
int u, v, a, b;
bool operator < (const ele A) const {return a < A.a;}
}p[N]; int fa[N], ch[N][2], maxn[N], val[N], rev[N], wz[N], st[N], f[N], n, m, len, ans = INT_MAX; int isroot(int u) {return ch[fa[u]][0] != u && ch[fa[u]][1] != u;} int get(int u) {return ch[fa[u]][1] == u;} void update(int u) {
maxn[u] = val[u]; wz[u] = u;
if(maxn[ch[u][0]] > maxn[u] && ch[u][0]) maxn[u] = maxn[ch[u][0]], wz[u] = wz[ch[u][0]];
if(maxn[ch[u][1]] > maxn[u] && ch[u][1]) maxn[u] = maxn[ch[u][1]], wz[u] = wz[ch[u][1]];
} void pushdown(int u) {
if(rev[u]) {
swap(ch[u][0], ch[u][1]);
rev[ch[u][0]] ^= 1;
rev[ch[u][1]] ^= 1;
rev[u] ^= 1;
}
} void rotate(int u) {
int old = fa[u], oldd = fa[old], k = get(u);
if(!isroot(old)) ch[oldd][get(old)] = u; fa[u] = oldd;
ch[old][k] = ch[u][k ^ 1]; fa[ch[u][k ^ 1]] = old;
fa[old] = u; ch[u][k ^ 1] = old;
update(old); update(u);
} void splay(int u) {
st[len = 1] = u;
for(int i = u; !isroot(i); i = fa[i]) st[++len] = fa[i];
for(int i = len; i >= 1; i--) pushdown(st[i]);
for(; !isroot(u); rotate(u)) if(!isroot(fa[u])) rotate(get(u) == get(fa[u]) ? fa[u] : u);
} void access(int u) {
for(int i = 0; u; i = u, u = fa[u]) {
splay(u);
ch[u][1] = i;
update(u);
}
} void makeroot(int u) {
access(u);
splay(u);
rev[u] ^= 1;
} int findroot(int u) {
access(u); splay(u);
while(ch[u][0]) u = ch[u][0];
return u;
} void link(int u, int v) {
makeroot(u);
fa[u] = v;
} void cut(int u, int v) {
makeroot(u);
access(v);
splay(v);
fa[u] = ch[v][0] = 0;
update(v);
} int query(int u, int v) {
makeroot(u);
access(v);
splay(v);
return wz[v];
} int find(int x) {return f[x] == x ? x : f[x] = find(f[x]);} int main() {
read(n); read(m);
for(int i = 1; i <= n; i++) f[i] = i;
for(int i = 1; i <= m; i++) {
read(p[i].u); read(p[i].v);
read(p[i].a); read(p[i].b);
}
sort(p + 1, p + m + 1);
for(int i = 1; i <= m; i++) {
int x = p[i].u, y = p[i].v;
int A = p[i].a, B = p[i].b;
if(find(x) != find(y)) {
f[find(x)] = find(y);
val[i + n] = maxn[i + n] = B;
link(x, i + n); link(y, i + n);
} else {
if(x == y) continue;
int weizhi = query(x, y);
if(p[weizhi - n].b > B) {
cut(p[weizhi - n].u, weizhi);
cut(p[weizhi - n].v, weizhi);
val[i + n] = maxn[i + n] = B;
link(x, i + n); link(y, i + n);
}
}
if(find(1) == find(n)) ans = min(ans, p[query(1, n) - n].b + A);
}
if(ans == INT_MAX) cout << -1 << endl; else cout << ans << endl;
return 0;
}

luoguP2387 [NOI2014]魔法森林的更多相关文章

  1. NOI2014 魔法森林

    3669: [Noi2014]魔法森林 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 106  Solved: 62[Submit][Status] ...

  2. bzoj 3669: [Noi2014]魔法森林 动态树

    3669: [Noi2014]魔法森林 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 363  Solved: 202[Submit][Status] ...

  3. BZOJ 3669: [Noi2014]魔法森林( LCT )

    排序搞掉一维, 然后就用LCT维护加边MST. O(NlogN) ------------------------------------------------------------------- ...

  4. bzoj 3669: [Noi2014]魔法森林

    bzoj 3669: [Noi2014]魔法森林 Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号 ...

  5. BZOJ_3669_[Noi2014]魔法森林_LCT

    BZOJ_3669_[Noi2014]魔法森林_LCT Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节 ...

  6. bzoj 3669: [Noi2014]魔法森林 (LCT)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3669 题面: 3669: [Noi2014]魔法森林 Time Limit: 30 Sec  ...

  7. 「luogu2387」[NOI2014] 魔法森林

    「luogu2387」[NOI2014] 魔法森林 题目大意 \(n\) 个点 \(m\) 条边的无向图,每条边上有两个权值 \(a,b\),求从 \(1\) 节点到 \(n\) 节点 \(max\{ ...

  8. P2387 [NOI2014]魔法森林(LCT)

    P2387 [NOI2014]魔法森林 LCT边权维护经典题 咋维护呢?边化为点,边权变点权. 本题中我们把边对关键字A进行排序,动态维护关键字B的最小生成树 加边后出现环咋办? splay维护最大边 ...

  9. [NOI2014]魔法森林 LCT

    题面 [NOI2014]魔法森林 题解 一条路径的代价为路径上的\(max(a[i]) + max(b[i])\),因为一条边同时有$a[i], b[i]$2种权值,直接处理不好同时兼顾到,所以我们考 ...

随机推荐

  1. dd命令的高级应用

    dd是Linux上的一个常用的命令.例如:dd if=/1.txt of=/tmp/2.txt     (其中, if代表input file:of代表output file, 命令的结果就是将根目录 ...

  2. Postgresql VACUUM COPY等

    1.VACUUM VACUUM回收dead tuples占用的存储空间. 在一般的PostgreSQL操作中,被update操作删除或废弃的元组不会从物理表中删除; 它们一直存在,直到执行VACUUM ...

  3. MongDB安装使用

    4.MongoDB 下载 MongoDB 提供了可用于 32 位和 64 位系统的预编译二进制包,你可以从MongoDB官网下载安装,MongoDB 预编译二进制包下载地址:https://www.m ...

  4. JavaScript高级程序设计学习

    1.变量 变量使用var操作符定义,var message,定义一个message变量,可用来保存任何类型的变量.未经初始化的变量值为undifided: 如果没变量没有被var定义,那么被执行后会成 ...

  5. CE学习记录1

    主题 春节放假终于有空学习下怎么制作外挂啦......学习写外挂大概是我一开始学习计算机的动力吧....只是一直似懂非懂..看教学视频各种不明白为什么....也没有专门的时间学习下怎么写....春节有 ...

  6. Hbase 一次表异常,有一张表 无法count scan 一直显示重连

    z_activeagent z_weekstore z_wstest zz_monthstore row(s) in 0.5240 seconds => ["KYLIN_02YJ3NJ ...

  7. linux中memset的正确用法

    linux中memset的正确用法 [起因]希望对各种类型的数组进行初始化,避免野值 [函数头文件] 提示:在linux中可以在terminal中输入 "man memset"进行 ...

  8. 思考ASP.NET网站静态化的利与弊

    最近在思考网站要不要进行静态化的问题,在网上收集和整理了有关静态化利与弊的资料,于是写下此博文分享到网络上.由于本人是一名asp.net开发人员,所以本文的观点可能无法涉及到全部方面,但是比较注重于使 ...

  9. Linux下cacti的安装

    Cacti安装手册 第一步.  Cacti的架构 第二步. Cacti的工作流程 第三步. Cacti简介 1. cacti是用php语言实现的一个软件,它的主要功能是用snmp服务获取数据,然后用r ...

  10. 【转】http 缓存

    原文地址:https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-c ...