洛谷 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 ...
 
随机推荐
- restrict关键字
			
值得注意的是,一旦你决定使用restrict来修饰指针,你必须得保证它们之间不会互相重叠,编译器不会替你检查. 关键字restrict有两个读者.一个是编译器,它告诉编译器可以自由地做一些有关优化的假 ...
 - EasyUI 之 easyui-datagrid 字段格式化
			
后台返回的json格式: 列表字段要显示username 用户的真实姓名: formatter="formatterByUserName" <table id="d ...
 - js的45个技巧
			
JavaScript是一个绝冠全球的编程语言,可用于Web开发.移动应用开发(PhoneGap.Appcelerator).服务器端开发(Node.js和Wakanda)等等.JavaScript还是 ...
 - js返回上一层
			
Javascript 返回上一页 1. Javascript 返回上一页 history.go(-1), 返回两个页面: history.go(-2); 2. history.back(). wind ...
 - Prime Ring Problem   --  第一个真正意义上的   搜索
			
这个搜索............搜的我头都大了.......不过还是 懂了那么一点点...哈哈 从3/7晚上 做到3/8晚上------从女生到妇女 我都用来做着一道题了......... 所谓的 ...
 - 如何获取select控件的option值和Value?
			
案例: <select id="paId" class="text3"> <option value=& ...
 - ORA-01075: you are currently logged on
			
[root@hear01 ~]# su - oracle[oracle@hear01 ~]$ sqlplus "/as sysdba" SQL*Plus: Release 11.2 ...
 - python之 文件操作
			
一.初识文件操作 使用python来读写文件是非常简单的操作,我们使用open函数来打开一个文件,获取到 文件句柄,然后通过文件句柄就可以进行各种各样的操作,同过打开方式的不同能够执行的 操作也会有相 ...
 - android 虚拟机,文件导入sdcard下报错,Read-only file system
			
解决方案-------------------- eclipse -> windows->Android AVD Manager 里选择你的AVD,edit里SD Card 选择File, ...
 - python算数运算符
			
---恢复内容开始--- 加减乘除 >>> 1+1 2 >>> 4-2 2 >>> 2*5 10 >>> 8/2 4.0 > ...