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. python签名设计

    将一个签名网站http://www.uustv.com/的内容爬下来显示出来 代码:sign.py from tkinter import * from tkinter import messageb ...

  2. c++builder Active Form

    新增的属性.方法刷新一下才可以生成方法的实现.保存按钮不生成,刷新就好了. Refresh Implemention

  3. PyInstaller打包成exe可执行文件

    PyInstaller 安装pyinstaller 对于那些网络比较稳定,能够流畅使用pip源地址的用户,直接下面的命令就可以搞定: pip install pyinstaller 通常我们会下载源码 ...

  4. GIT常用命令以及作用【备忘】

    git commit  提交一个修改 git branch branchName  新建一个branchName的分支 git merge branchName 将当前分支与branchName分支合 ...

  5. laravel 验证机制validation

    Laravel 中 validation 验证 返回中文提示 全局设置 自己建一个zn文件夹,然后把en的4个文件全复制过去,修改validation.php的代码为下面的内容,然后在app.php修 ...

  6. Android selector中的item的顺序

    在selector中,要将默认状态的item放在最后面,因为一旦前面的item满足匹配条件,后面的item就不会去匹配.因此,把默认状态的item放在前面的话,后面的item没有执行的机会

  7. SpringCloud03 Ribbon知识点、 Feign知识点、利用RestTemplate+Ribbon调用远程服务提供的资源、利用feign调用远程服务提供的资源、熔断

    1 远程服务资源的调用 1.1 古老的套路 在微服务出现之前,所有的远程服务资源必须通过RestTemplate或者HttpClient进行:但是这两者仅仅实现了远程服务资源的调用,并未提供负载均衡实 ...

  8. 599. Minimum Index Sum of Two Lists两个餐厅列表的索引和最小

    [抄题]: Suppose Andy and Doris want to choose a restaurant for dinner, and they both have a list of fa ...

  9. oracle 通过序列实现某字段自增

    -- 创建表 create table items( id int primary key, name ) not null, price int not null, detail ), pic ), ...

  10. 黑盒测试实践--Day6 11.30

    黑盒测试实践--Day6 11.30 今天完成任务情况: 应用设计的场景用例,完成测试用例的编写 完成测试用例在自动化测试工具QTP上的测试 分析测试结果得到缺陷报告 小靳 软件测试 今天主要钻研了q ...