题面

题意:

给出一个图,边权有两维,ab. 求1n的一条路径使得路径经过的边的最大的ab的和最小,输出最小之和。

\(Solution:\)

如果做过这题,那么就显得很简单了很好想了。

又是想让路径上最大的边权尽可能小,于是就想到先对 b 从小到大 Kruscal 加边,然后维护链上 a 的最大边,如果当前 link(u,v) 成环了,假设之前 uv 路径上最大边是 x->y , 如果 x->y.a > u->v.acut(x,y),link(u,v).

\(Source\)

#include <set>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <assert.h>
#include <algorithm> using namespace std; #define fir first
#define sec second
#define pb push_back
#define mp make_pair
#define LL long long
#define INF (0x3f3f3f3f)
#define mem(a, b) memset(a, b, sizeof (a))
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define ____ debug("go")
#define Debug(x) cout << #x << " = " << x << endl
#define tralve(i, x) for (register int i = head[x]; i; i = nxt[i])
#define For(i, a, b) for (register int (i) = (a); (i) <= (b); ++ (i))
#define Forr(i, a, b) for (register int (i) = (a); (i) >= (b); -- (i))
#define file(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout) namespace io {
static char buf[1<<21], *pos = buf, *end = buf;
inline char getc()
{ return pos == end && (end = (pos = buf) + fread(buf, 1, 1<<21, stdin), pos == end) ? EOF : *pos ++; }
inline int rint() {
register int x = 0, f = 1;register char c;
while (!isdigit(c = getc())) if (c == '-') f = -1;
while (x = (x << 1) + (x << 3) + (c ^ 48), isdigit(c = getc()));
return x * f;
}
inline LL rLL() {
register LL x = 0, f = 1; register char c;
while (!isdigit(c = getc())) if (c == '-') f = -1;
while (x = (x << 1ll) + (x << 3ll) + (c ^ 48), isdigit(c = getc()));
return x * f;
}
inline void rstr(char *str) {
while (isspace(*str = getc()));
while (!isspace(*++str = getc()))
if (*str == EOF) break;
*str = '\0';
}
template<typename T>
inline bool chkmin(T &x, T y) { return x > y ? (x = y, 1) : 0; }
template<typename T>
inline bool chkmax(T &x, T y) { return x < y ? (x = y, 1) : 0; }
}
using namespace io; const int N = 2e5 + 1; int n, m, Fa[N];
struct Edge { int u, v, a, b; } E[N];
bool operator<(Edge a, Edge b) { return a.b < b.b; } namespace LCT {
#define ls (ch[x][0])
#define rs (ch[x][1])
#define chk(x) (ch[fa[x]][1] == x) int top, stk[N];
int ch[N][2], fa[N], mxid[N], id[N], rev[N]; void init(int x, int y) {
if (x > n) mxid[x] = id[x] = y;
}
bool irt(int x) {
return x != ch[fa[x]][0] && x != ch[fa[x]][1];
}
void pu(int x) {
mxid[x] = id[x];
if (ls && E[mxid[x]].a < E[mxid[ls]].a) mxid[x] = mxid[ls];
if (rs && E[mxid[x]].a < E[mxid[rs]].a) mxid[x] = mxid[rs];
}
void pd(int x) {
if (rev[x]) {
swap(ch[ls][0], ch[ls][1]); rev[ls] ^= 1;
swap(ch[rs][0], ch[rs][1]); rev[rs] ^= 1;
rev[x] = 0;
}
}
void rot(int x) {
int y = fa[x], z = fa[y], k = chk(x), tmp = ch[x][k ^ 1];
ch[y][k] = tmp, fa[tmp] = y;
if (!irt(y)) ch[z][chk(y)] = x; fa[x] = z;
ch[x][k ^ 1] = y, fa[y] = x;
pu(y); pu(x);
}
void splay(int x) {
stk[top = 1] = x; for (int i = x; !irt(i); i = fa[i]) stk[++top] = fa[i];
while (top) pd(stk[top--]);
while (!irt(x)) {
int y = fa[x], z = fa[y];
if (!irt(y))
if (chk(x) == chk(y)) rot(y);
else rot(x);
rot(x);
}
}
void access(int x) {
for (int y = 0; x; x = fa[y = x]) splay(x), ch[x][1] = y, pu(x);
}
int findroot(int x) {
access(x); splay(x); pd(x); while (ch[x][0]) x = ch[x][0], pd(x); splay(x); return x;
}
void makeroot(int x) {
access(x); splay(x); swap(ls, rs); rev[x] ^= 1;
}
void split(int x, int y) {
makeroot(x); access(y); splay(y);
}
void link(int x, int y) {
makeroot(x); fa[x] = y;
}
void cut(int x, int y) {
split(x, y); ch[y][0] = fa[x] = 0;
}
} int find(int x) {
return Fa[x] == x ? x : Fa[x] == find(Fa[x]);
}
void merge(int x, int y) {
Fa[find(x)] = find(y);
} int main() {
#ifndef ONLINE_JUDGE
file("P2387");
#endif
n = rint(), m = rint();
For (i, 1, m) {
E[i].u = rint(), E[i].v = rint(), E[i].a = rint(), E[i].b = rint();
}
sort(E + 1, E + 1 + m);
For (i, 1, n + m) Fa[i] = i; For (i, n + 1, m + n) LCT::init(i, i - n); int ans = INF;
For (i, 1, m) {
//____;
int u = E[i].u, v = E[i].v;
if (LCT::findroot(u) == LCT::findroot(v)) {
LCT::split(u, v);
int Maxid = LCT::mxid[v];
if (E[i].a < E[Maxid].a) {
LCT::cut(E[Maxid].u, Maxid + n); LCT::cut(Maxid + n, E[Maxid].v);
LCT::link(u, i + n); LCT::link(i + n, v);
}
} else {
LCT::link(u, i + n); LCT::link(i + n, v);
}
if (LCT::findroot(1) == LCT::findroot(n)) {
LCT::split(1, n); int Maxid = LCT::mxid[n];
chkmin(ans, E[i].b + E[Maxid].a);
}
}
printf("%d\n", ans == INF ? -1 : ans);
}

[P2387魔法森林的更多相关文章

  1. 洛谷—— P2387 魔法森林

    题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2,3,…,n,边标号为 1,2,3,…, ...

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

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

  3. 洛谷 P2387 [NOI2014]魔法森林 解题报告

    P2387 [NOI2014]魔法森林 题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2 ...

  4. 洛谷P2387 [NOI2014]魔法森林(lct维护最小生成树)

    题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2,3,…,n,边标号为 1,2,3,…, ...

  5. AC日记——魔法森林 洛谷 P2387

    魔法森林 思路: spfa水过(正解lct); 代码: #include <bits/stdc++.h> using namespace std; #define maxn 50005 # ...

  6. P2387 [NOI2014]魔法森林 LCT维护最小生成树

    \(\color{#0066ff}{ 题目描述 }\) 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 ...

  7. 洛谷P2387 [NOI2014]魔法森林(LCT)

    魔法森林 题目传送门 解题思路 把每条路按照\(a\)的值从小到大排序.然后用LCT按照b的值维护最小生成树,将边按照顺序放入.如果\(1\)到\(n\)有了一条路径,就更新最小答案.这个过程就相当于 ...

  8. BZOJ3669:[NOI2014]魔法森林——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=3669 https://www.luogu.org/problemnew/show/P2387 为了得 ...

  9. 【BZOJ3669】[Noi2014]魔法森林 LCT

    终于不是裸的LCT了...然而一开始一眼看上去这是kruskal..不对,题目要求1->n的路径上的每个点的两个最大权值和最小,这样便可以用LCT来维护一个最小生成路(瞎编的...),先以a为关 ...

随机推荐

  1. 如何解决mosh中翻页只能查看一屏的问题

    最近用mosh替换了ssh作为连接开发机的工具,发现另外一个问题,ls cat随便什么命令输出结果超过一行的,向上翻页就没有了,找了下官网的FAQ也提到了这个问题,目前解决方案是使用tmux或者scr ...

  2. Code First 一

    Code-First和我们的数据库优先方式是相反的,数据库优先是通过数据库映射出相应的类和上下文,Code-First测试通过创建的类和上下文得到相应的数据库. Code-First主要用于领域驱动设 ...

  3. VMware虚拟机修改BIOS启动项

    vmware默认是硬盘启动,要进bios里面设置成开机的启动顺序,要将光盘设置成第一启动项.但vm的开机画面比笔记本的还要快很多,基本都在1s内的,想进入 bios里面也有难度.. 对于网上说的开vm ...

  4. SpringBoot非官方教程 | 第二十六篇: sprinboot整合elk,搭建实时日志平台

    转载请标明出处: 原文首发于https://www.fangzhipeng.com/springboot/2017/07/11/sprinboot25-elk/ 本文出自方志朋的博客 这篇文章主要介绍 ...

  5. Python 学习笔记(八)Python列表(一)

    列表基本操作 列表(list)定义  列表是Python中的一种对象类型,也是一种序列 对象类型:list 表示方法:[ ] python 列表中的元素可以是任何类型的对象 >>> ...

  6. linux 怎么查看系统的环境变量 与设置jdk 系统环境变量

    1.win 7 ,win10 怎么查看,添加系统环境的变量,大家都非常清楚的.但是linux 的 却不一定哦. 打开终端输入 :  “echo $PATH “ or  “export ”      如 ...

  7. mysql if...else 的使用

    select case when tca.id = '3' then 'vw' else epc_code end as epccode,tfp.product_id, tfp.vender, tfp ...

  8. Sass 基础(五)

    @if @if 指令是一个SassScript,它可以根据条件处理样式块,如果条件为true返回一个样式块,反之 false 返回另一个样式块,在Sass 中除了@if之,还可以配合@else if和 ...

  9. Percona-Tookit工具包之pt-index-usage

      Preface       There're many ways relevent with performance tuning.For example,using indexes proper ...

  10. 爬虫——正则表达式re模块

    为什么要学习正则表达式 实际上爬虫一共就四个主要步骤: 明确目标:需清楚目标网站 爬:将所有的目标网站的内容全部爬下来 取:在爬下来的网站内容中去掉对我们没有用处的数据,只留取我们需要的数据 处理数据 ...