[P2387魔法森林
题面
题意:
给出一个图,边权有两维,a与b. 求1到n的一条路径使得路径经过的边的最大的a与b的和最小,输出最小之和。
\(Solution:\)
如果做过这题,那么就显得很简单了很好想了。
又是想让路径上最大的边权尽可能小,于是就想到先对 b 从小到大 Kruscal 加边,然后维护链上 a 的最大边,如果当前 link(u,v) 成环了,假设之前 u 到 v 路径上最大边是 x->y , 如果 x->y.a > u->v.a 就 cut(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魔法森林的更多相关文章
- 洛谷—— P2387 魔法森林
题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2,3,…,n,边标号为 1,2,3,…, ...
- P2387 [NOI2014]魔法森林(LCT)
P2387 [NOI2014]魔法森林 LCT边权维护经典题 咋维护呢?边化为点,边权变点权. 本题中我们把边对关键字A进行排序,动态维护关键字B的最小生成树 加边后出现环咋办? splay维护最大边 ...
- 洛谷 P2387 [NOI2014]魔法森林 解题报告
P2387 [NOI2014]魔法森林 题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2 ...
- 洛谷P2387 [NOI2014]魔法森林(lct维护最小生成树)
题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2,3,…,n,边标号为 1,2,3,…, ...
- AC日记——魔法森林 洛谷 P2387
魔法森林 思路: spfa水过(正解lct); 代码: #include <bits/stdc++.h> using namespace std; #define maxn 50005 # ...
- P2387 [NOI2014]魔法森林 LCT维护最小生成树
\(\color{#0066ff}{ 题目描述 }\) 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 ...
- 洛谷P2387 [NOI2014]魔法森林(LCT)
魔法森林 题目传送门 解题思路 把每条路按照\(a\)的值从小到大排序.然后用LCT按照b的值维护最小生成树,将边按照顺序放入.如果\(1\)到\(n\)有了一条路径,就更新最小答案.这个过程就相当于 ...
- BZOJ3669:[NOI2014]魔法森林——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=3669 https://www.luogu.org/problemnew/show/P2387 为了得 ...
- 【BZOJ3669】[Noi2014]魔法森林 LCT
终于不是裸的LCT了...然而一开始一眼看上去这是kruskal..不对,题目要求1->n的路径上的每个点的两个最大权值和最小,这样便可以用LCT来维护一个最小生成路(瞎编的...),先以a为关 ...
随机推荐
- Java运行时异常与一般异常以及错误的异同
Java提供了两类主要的异常:runtime exception和checked exception.checked 异常也就是我们经常遇到的IO异常,以及SQL异常都是这种异常.对于这种异常,JAV ...
- 根据GB2312编码表求汉字字节
java中有8种基本数据类型,byte,short,int,long,float,double,boolean byte用1个字节表示,占8比特,取值范围 负2的7次方至正2的7次方减1 二进制000 ...
- 【题解】UVA756 Biorhythms (中国剩余定理)
UVA756:https://www.luogu.org/problemnew/show/UVA756 思路 几乎是裸的中国剩余定理模板题 但是需要注意的是此题并不是求最小正整数解 而是求大于d的解 ...
- TridentState分析
public class TridentState { TridentTopology _topology; Node _node; protected TridentState(TridentTop ...
- 对象API
遍历对象里的每个元素 var obj ={ a:32, b:12, c :342 } for (const key of obj){ if(obj.hasOwnProperty(key)){ cons ...
- ETO的公开赛T5《猎杀蓝色空间号》题解
这道题别看题面这么长,其实题意很简单 就是让你求从起点开始的最长合法区间 合法的要求有两个:兜圈子和直飞 且这两个条件相互独立 (也就是说兜圈子的末尾不会对下面可能出现的直飞造成影响) 举个例子: 1 ...
- Spring+SpringMVC+Mybatis(二)
上一次讲的是利用mybatis提供的sqlSessionTemplate作为DAO进行数据库的操作,其实我们可以把它封装到我们自己的DAO里面,这样就是所谓的自己写DAO,这次我们写一下通过mybat ...
- Java中事务总结详解(精华)
1.什么是JAVA事务? 通常的观念认为,事务仅与数据库相关. 事务必须服从ISO/IEC所制定的ACID原则.ACID是原子性(atomicity).一致性(consistency).隔离性 (is ...
- JZOJ 5943. 树
Description
- 判断不同浏览器,加载不同的css和js文件
在低版本的IE中,条件注释还有效果,但是在ie9,10,11浏览器中,条件注释不起作用. 在网上找了个校验ie的方法. function isIE(){ if (window.ActiveXObje ...