洛谷 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 ...
随机推荐
- cojs1101. [Vijos1369] 难解的问题==codevs 2188 最长上升子序列
[题目描述] 在你的帮助下,蔚蓝来到了埃及.在金字塔里,蔚蓝看到了一个问题,传说,能回答出这个问题的人就能受到埃及法老的祝福,可是蔚蓝日夜奋战,还是想不出来,你能帮帮他么?(XXX: 胡扯,教主怎么可 ...
- linux命令 - free -m
如下显示free是显示的当前内存的使用,-m的意思是M字节来显示内容.我们来一起看看. [root@zabbix ~]# free -m total used free shared buffers ...
- cookie应用(一周内免登陆)
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...
- js addeventlistener 刮刮贴
<!doctype html><html><head><meta charset="utf-8"><title>无标题文 ...
- P3194 [HNOI2008]水平可见直线
传送门 我们把所有的直线按斜率从小到大排序,然后用单调栈维护 发现,如果当前直线与\(st[top-1]\)直线的交点的横坐标大于等于与\(st[top]\)的交点的横坐标,当前直线可以覆盖掉\(st ...
- Akka源码分析-Actor&ActorContext&ActorRef&ActorCell
分析源码的过程中我们发现,Akka出现了Actor.ActorRef.ActorCell.ActorContext等几个相似的概念,它们之间究竟有什么区别和联系呢? /** * Actor base ...
- 网络简要<入门篇>
OSI七层 网络的含义:两个不在同一地理位置的主机(终端),通过传输介质和通信协议,实现通信和资源共享. 网络四要素:终端,传输介质 ,通信协议,资源 网络分类: 以范围分类:LAN网(局域网,以太网 ...
- SQL数据库还原的二种方式和区别
1.数据库还原 在SQL中,直接选择选择“还原数据库”:选中.bak 文件即可. 2.生成脚本 新建同样的DB名字,在SQL打开脚本,执行脚本语言.数据库里面就会自动填充内容.
- sql数据库中常用连接
很简单的知识点,今天有点搞不清楚左外连接,右外连接:详见以下: --表stu id name 1, Jack 2, Tom 3, Kity 4, nono --表exam id grade 1, 56 ...
- NHibernate系列学习(一)-看看用NH怎么做增速改查
1.本次所有代码是在一下环境下运行的 学习系统:win8 64bit 开发环境:VS2013,MSSQL2012 NHibernate版本:NHibernate-4.0.3.GA [文章结尾有本次笔记 ...