洛谷 2387 NOI2014魔法森林 LCT

【题解】
我们先把边按照$a$值从小到大排序,并按照这个顺序加边。
如果当前要加入的边连接的两点$u$与$v$已经是连通的,那么直接加入这条边就会出现环。这时我们需要删除这个环中$b$值最大的边。因此我们需要维护区间最大值,以及最大值的位置。
如果当前$1$与$n$已经连通,就更新$ans$,当前从$1~n$的代价是$ai+val[querymax(1,n)]$;
为了方便处理,我们可以把边开成点,即加边的时候多开一个表示这条边的点,在上面记录边权等信息。
#include<cstdio>
#include<algorithm>
#define N (500010)
#define inf (2e9)
#define ls (c[u][0])
#define rs (c[u][1])
using namespace std;
int n,m,ans;
inline int read(){
int k=,f=; char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(''<=c&&c<='')k=k*+c-'',c=getchar();
return k*f;
}
struct edge{int u,v,a,b;}e[N];
struct Link_cut_tree{
int top,c[N][],fa[N],rev[N],q[N],maxpos[N],val[N];
inline void pushdown(int u){
if(rev[u]) rev[ls]^=,rev[rs]^=,rev[u]^=,swap(ls,rs);
}
inline void pushup(int u){
maxpos[u]=u;
if(val[maxpos[ls]]>val[maxpos[u]]) maxpos[u]=maxpos[ls];
if(val[maxpos[rs]]>val[maxpos[u]]) maxpos[u]=maxpos[rs];
}
inline bool isroot(int u){
return c[fa[u]][]!=u&&c[fa[u]][]!=u;
}
inline bool which(int u){
return c[fa[u]][]==u;
}
void rotate(int u){
int f=fa[u],gf=fa[f],wh=which(u);
if(!isroot(f)) c[gf][which(f)]=u;
fa[u]=gf; fa[f]=u; fa[c[u][wh^]]=f;
c[f][wh]=c[u][wh^]; c[u][wh^]=f;
pushup(f); pushup(u);
}
void splay(int u){
q[top=]=u;
for(int i=u;!isroot(i);i=fa[i]) q[++top]=fa[i];
for(int i=top;i;i--) pushdown(q[i]);
while(!isroot(u)){
if(!isroot(fa[u])) rotate(which(fa[u])==which(u)?fa[u]:u);
rotate(u);
}
pushup(u);
}
void access(int u){
for(int son=;u;son=u,u=fa[u]) splay(u),c[u][]=son,pushup(u);
}
void makeroot(int u){
access(u); splay(u); rev[u]^=;
}
int find(int u){
access(u); splay(u);
while(ls) u=ls;
return u;
}
void split(int x,int y){
makeroot(x); access(y); splay(y);
}
void cut(int x,int y){
split(x,y);
c[y][]=fa[x]=;
pushup(y);
}
void link(int x,int y){
makeroot(x); fa[x]=y;
}
int query(int x,int y){
makeroot(x); access(y); splay(y);
return maxpos[y];
}
}t;
bool cmp(edge x,edge y){
return x.a<y.a;
}
int main(){
ans=inf;
n=read(); m=read();
for(int i=;i<=m;i++)
e[i].u=read(),e[i].v=read(),e[i].a=read(),e[i].b=read();
sort(e+,e+m+,cmp);
for(int i=;i<=m;i++){
int u=e[i].u,v=e[i].v,a=e[i].a,b=e[i].b;
if(t.find(u)==t.find(v)){
int pos=t.query(u,v);
if(t.val[pos]>b){
t.cut(pos,e[pos-n].u);
t.cut(pos,e[pos-n].v);
}
else{
if(t.find()==t.find(n)) ans=min(ans,a+t.val[t.query(,n)]);
continue;
}
}
t.val[n+i]=b; t.maxpos[n+i]=n+i;
t.link(u,n+i); t.link(v,n+i);
if(t.find()==t.find(n)) ans=min(ans,a+t.val[t.query(,n)]);
}
if(ans==inf) puts("-1");
else printf("%d\n",ans);
return ;
}
洛谷 2387 NOI2014魔法森林 LCT的更多相关文章
- 洛谷P2387 [NOI2014]魔法森林(LCT)
魔法森林 题目传送门 解题思路 把每条路按照\(a\)的值从小到大排序.然后用LCT按照b的值维护最小生成树,将边按照顺序放入.如果\(1\)到\(n\)有了一条路径,就更新最小答案.这个过程就相当于 ...
- 洛谷2387 NOI2014魔法森林(LCT维护最小生成树)
本题是运用LCT来维护一个最小生成树. 是一个经典的套路 题目中求的是一个\(max(a_i)+max(b_i)\)尽可能小的路径. 那么这种的一个套路就是,先按照一维来排序,然后用LCT维护另一维 ...
- 洛谷 P2387 [NOI2014]魔法森林 解题报告
P2387 [NOI2014]魔法森林 题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2 ...
- 洛谷P2387 [NOI2014]魔法森林(lct维护最小生成树)
题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2,3,…,n,边标号为 1,2,3,…, ...
- 洛谷P2387 [NOI2014]魔法森林(LCT,Splay)
在XZY&XZZ巨佬的引领下,一枚蒟蒻终于啃动了这道题...... 这次还是第一次写LCT维护边权,还要化边为点,思路乱七八糟的,写起来也不顺手,还好调了许久终于AC啦. 贪心排序按一个关键字 ...
- 洛谷P2387 [NOI2014]魔法森林(LCT)
在XZY&XZZ巨佬的引领下,一枚蒟蒻终于啃动了这道题...... 这次还是第一次写LCT维护边权,还要化边为点,思路乱七八糟的,写起来也不顺手,还好调了许久终于AC啦. 贪心排序按一个关键字 ...
- 洛谷2387 BZOJ3669魔法森林题解
题目链接 BZ链接 这道题被很多人用spfa水了过去,表示很... 其实spfa很好卡,这组数据可以卡掉大多数spfa 链接:密码:rjvk 这里讲一下LCT的做法 我们按照a将边排序,然后依次添加 ...
- BZOJ 3669: [Noi2014]魔法森林( LCT )
排序搞掉一维, 然后就用LCT维护加边MST. O(NlogN) ------------------------------------------------------------------- ...
- bzoj 3669: [Noi2014]魔法森林 (LCT)
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3669 题面: 3669: [Noi2014]魔法森林 Time Limit: 30 Sec ...
随机推荐
- js【面向过程编程】、好、 【init()、 GetData()、 bindData()、bindDom、 bindEvent()、buyProduct()、AddProductToCart()】*****************
1. 一般页面开发方式 [可读性差.可维护性差]------初级开发工程师 一般页面编写方法 var name = 'iphone8' var description = '手机中的战斗机 ' var ...
- bzoj2073
状压dp 预处理每个状态的初始值,枚举子集就行了 #include<bits/stdc++.h> using namespace std; , inf = ; int W, n; < ...
- sql数据库CHECKDB时报x个分配错误和x个一致性错误
--1.在SQL查询分析器中执行以下语句:(注以下所用的POS为数据库名称,请用户手工改为自己的数据库名) use pos dbcc checkdb --2.查看查询结果,有很多红色字体显示,最后结果 ...
- jquery插件开发基本步骤
一.介绍 插件编写的目的是给已经有的一系列方法或函数做一个封装,以便在其他地方重复使用,方便后期维护. JQuery除了提供一个简单.有效的方式进行管理元素以及脚本,它还还提供了例外一种机制:即给核心 ...
- [App Store Connect帮助]二、 添加、编辑和删除用户(5)创建一个沙盒测试员帐户
如果您的 App 使用了 App 内购买项目或 Apple Pay,您可以在 App Store Connect 中创建沙盒测试员帐户,以便您向用户提供该 App 前,可以使用该帐户在测试环境中运行您 ...
- [Swift通天遁地]七、数据与安全-(6)管理文件夹和创建并操作文件
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- Java里边什么是值传递和引用传递?两个有什么区别
学过java基础的人都知道,在java中参数的传递过程中有值传递和应用传递,那么这两个到底有什么区别呢,下面我通过例子为大家详细的介绍下. 我们都知道Java中有八种数据类型,基础数据类型分别是:by ...
- 【USACO2006 Mar】滑雪缆车 skilift
[USACO2006 Mar] 滑雪缆车 skilift Time Limit 1000 msMemory Limit 131072 KBytes Description 科罗拉多州的罗恩打算为奶牛建 ...
- [ SHOI 2014 ] 概率充电器
\(\\\) \(Description\) 一个含\(N\)个元器件的树形结构充电器,第\(i\)个元器件有\(P_i\)的概率直接从外部被充电,连接\(i,j\)的边有\(P_{i,j}\)的概率 ...
- 第一次android混淆实战
第一次混淆,主要是因为引用本地第三方jar包的问题.虽然说本地第三方jar包自动避免混淆,但一些本地第三方jar包下的一些包要避免混淆.比如: 文中的com.org 这些包名都要避免混淆. 下面是我用 ...