题面

题意:

给出一个图,边权有两维,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. GOPL第三章练习题3.3 3.4代码

    练习3.3是peak展示为红色,valley展示为蓝色. 练习3.4是将svg图像打印到浏览器中. // Copyright © 2016 Alan A. A. Donovan & Brian ...

  2. 122. Best Time to Buy and Sell Stock II ——LeetCode

    Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...

  3. webapi2返回 已拒绝为此请求授权。

    开始用的webapi2中是没有问题的,后来再项目中加了个过滤器并继承了AuthorizeAttribute 然后在全球文件中注册你的过滤器,让每次执行的时候都会进来 我项目中只重写了OnAuthori ...

  4. Golang 字符串转URLCode

    Golang 字符串转URLCode 最近因调用gitlab API,在生成某些字符串的时候直接请求 gitlab API 失败, url如下: keysURL := "http://192 ...

  5. 涉及自制系统AS的几个协议总结

    IGP(Interior Gateway Protocol): 内部网关协议的总称:其下有RIP和OSPF EGP(External Gateway Protocol): 外部网关协议的总称:目前使用 ...

  6. 使用终端命令行将本地项目上传到Github并提交代码

    第一步: 在Github上创建自己的repository 第二步:建立本地仓库cd到你的本地项目根目录下,执行git命令 1:$ cd 到你的项目目录下 2:$ git init 第三步:将本地项目工 ...

  7. udt通信java再次升级1.1版

    以前完成了udt的java代码测试,功能基本完成,近几天有时间重新梳理了下源码: 对原通信的关闭统一了方法,close定位过时,由shutdown与shutdownNow代替. 将一些主要方法添加了注 ...

  8. 关于Mobius反演

    欧拉函数 \(\varphi\) \(\varphi(n)=\)表示不超过 \(n\) 且与 \(n\) 互质的正整数的个数 \[\varphi(n)=n\cdot \prod_{i=1}^{s}(1 ...

  9. 三种for循环遍历

    import java.util.ArrayList;import java.util.Iterator;import java.util.List; public class  For{ publi ...

  10. ansible-palybook剧本

    1 ansible基础知识部分补充 1.1 ansible软件特点: · 可以实现批量管理 · 可以实现批量部署 · ad-hoc(批量执行命令)---针对临时性的操作 ansible clsn -m ...