[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为关 ...
随机推荐
- EJB结合struts2创建项目、发布jboss服务器和访问、父类(BaseDaoImpl)的封装
一.环境搭建: 1.准备jboss服务器,将对应数据库的xml配置好放到jboss的发布目录下. <?xml version="1.0" encoding="UTF ...
- 菜鸟崛起 DB Chapter 2 MySQL 5.6的概述与安装
在上文菜鸟崛起 DB Chapter 1 数据库概述我们初步认识了数据库,也知道市面上常见的几种数据库,下面我们就针对常见的MySQL数据库展开对DataBase的探讨. 2.1 MySQL介绍 M ...
- C++定义一个简单的Computer类
/*定义一个简单的Computer类 有数据成员芯片(cpu).内存(ram).光驱(cdrom)等等, 有两个公有成员函数run.stop.cpu为CPU类的一个对象, ram为RAM类的一个对象, ...
- OCCI开发环境搭建(Ubuntu)
OCCI开放包(下载与服务器版本相同的开发包, 这用的是12.1.0.2): instantclient-basic-linux.x64-12.1.0.2.0.zip instantclient-sd ...
- hdu 3966 Aragorn's Story : 树链剖分 O(nlogn)建树 O((logn)²)修改与查询
/** problem: http://acm.hdu.edu.cn/showproblem.php?pid=3966 裸板 **/ #include<stdio.h> #include& ...
- Struts2进阶学习4
Struts2进阶学习4 自定义拦截器的使用 核心配置文件 <?xml version="1.0" encoding="UTF-8"?> <! ...
- (四)、python 集合与格式化
一.set 集合 集合:可以包含多个元素,用逗号分割“,” 集合的作用:去重,关系运算, 1.不同元素组成2.无序3.集合中元素必须是不可变类型(可hash,可作为字典的key) 使用方法: 1) ...
- javaWeb项目加载HTML文件时报错 [No Find /index.html]
直接上主题: 在web.xml文件中添加如下信息: <display-name>Spring MVC Application</display-name> <servle ...
- Leecode刷题之旅-C语言/python-35.搜索插入位置
/* * @lc app=leetcode.cn id=35 lang=c * * [35] 搜索插入位置 * * https://leetcode-cn.com/problems/search-in ...
- 8-C++远征之继承篇-学习笔记
C++远征之继承篇 开篇介绍 整个C++远征计划: 起航->离港->封装->继承 为什么要用继承? 为什么要有继承? 如何来定义基类 <----> 派生类? 基类到派生类 ...