[BZOJ3669] [NOI2004] 魔法森林 LCT维护最小生成树
题面
一开始看到这道题虽然知道是跟LCT维护最小生成树相关的但是没有可以的去想。
感觉可以先二分一下总的精灵数,但是感觉不太好做。
又感觉可以只二分一种精灵,用最小生成树算另一种精灵,但是和似乎不单调。
然后就可以自然地想到先把边按\(a\)从小到大加入,用LCT维护最小生成树,直接更新答案即可。
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define REP(i,a,n) for(register int i(a);i<=(n);++i)
#define dbg(...) fprintf(stderr,__VA_ARGS__)
#define lc t[o].c[0]
#define rc t[o].c[1]
const int SZ=(1<<21)+1;char ibuf[SZ],*iS,*iT,obuf[SZ+128],*oS=obuf,*oT=obuf+SZ-1;
#ifndef ONLINE_JUDGE
#define gc() getchar()
#else
#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SZ,stdin),iS==iT?EOF:*iS++):*iS++)
#endif
template<typename I>inline void read(I&x){char c=gc();int f=1;for(;c<'0'||c>'9';c=gc())c=='-'?f=-1:0;for(x=0;c>='0'&&c<='9';c=gc())x=(x<<1)+(x<<3)+(c&15);f==-1?x=-x:0;}
typedef long long ll;typedef unsigned long long ull;
template<typename A,typename B>inline char SMAX(A&a,const B&b){return a<b?a=b,1:0;}
template<typename A,typename B>inline char SMIN(A&a,const B&b){return a>b?a=b,1:0;}const int N=50000+7,M=1e5+7;
int n,m,ans=0x3f3f3f3f;
struct Edges{int x,y,a,b;inline char operator<(const Edges&x)const{return a<x.a||(a==x.a&&b<x.b);}}e[M];//错误笔记:一定要加const!!!! struct Node{int c[2],fa,v,max,pos,rev;}t[N+M];int S[N+M],top;
inline char Isroot(int o){return t[t[o].fa].c[0]!=o&&t[t[o].fa].c[1]!=o;}
inline char Identify(int o){return t[t[o].fa].c[1]==o;}
inline void Connect(int fa,int o,int d){t[fa].c[d]=o;t[o].fa=fa;}
inline void Pushup(int o){t[o].max=t[o].v;t[o].pos=o;if(SMAX(t[o].max,t[lc].max))t[o].pos=t[lc].pos;if(SMAX(t[o].max,t[rc].max))t[o].pos=t[rc].pos;}
inline void Rotate(int o){int fa=t[o].fa,pa=t[fa].fa,d1=Identify(o),d2=Identify(fa),b=t[o].c[d1^1];if(!Isroot(fa))t[pa].c[d2]=o;t[o].fa=pa;Connect(fa,b,d1);Connect(o,fa,d1^1);Pushup(fa),Pushup(o);}
inline void Pushdown(int o){if(t[o].rev){t[o].rev=0;if(lc)t[lc].rev^=1,std::swap(t[lc].c[0],t[lc].c[1]);if(rc)t[rc].rev^=1,std::swap(t[rc].c[0],t[rc].c[1]);}}
inline void Splay(int o){int x=o;S[top=1]=x;while(!Isroot(x))S[++top]=x=t[x].fa;while(top)Pushdown(S[top--]);while(!Isroot(o)){int fa=t[o].fa;if(Isroot(fa))Rotate(o);else if(Identify(o)==Identify(fa))Rotate(fa),Rotate(o);else Rotate(o),Rotate(o);}
}
inline void Access(int o){for(register int x=0;o;o=t[x=o].fa)Splay(o),rc=x,Pushup(o);}
inline void Makeroot(int o){Access(o);Splay(o);t[o].rev^=1;std::swap(lc,rc);}
inline int Findroot(int o){Access(o);Splay(o);while(lc)Pushdown(o),o=lc;Splay(o);return o;}
inline void Split(int x,int y){Makeroot(x);Access(y);Splay(y);}
inline void Link(int x,int y){Makeroot(x);if(Findroot(y)!=x)t[x].fa=y;}
inline void Cut(int x,int y){Split(x,y);if(t[y].c[0]&&!t[x].c[1])t[y].c[0]=t[x].fa=0;Pushup(y);}int main(){read(n),read(m);REP(i,1,m)read(e[i].x),read(e[i].y),read(e[i].a),read(e[i].b);std::sort(e+1,e+m+1);REP(i,1,m){const int&x=e[i].x,&y=e[i].y,&a=e[i].a,&b=e[i].b;Makeroot(x);Access(y);Splay(x);const int d=t[x].max,p=t[x].pos;if(Findroot(x)!=Findroot(y))t[i+n].v=t[i+n].max=b,t[i+n].pos=i+n,Link(e[i].x,i+n),Link(e[i].y,i+n);else if(b<d)Cut(p,e[p-n].x),Cut(p,p[e-n].y),t[i+n].v=t[i+n].max=b,t[i+n].pos=i+n,Link(e[i].x,i+n),Link(e[i].y,i+n);if(Findroot(1)==Findroot(n))Split(1,n),SMIN(ans,a+t[n].max);}printf("%d\n",ans==0x3f3f3f3f?-1:ans);
}
转载于:https://www.cnblogs.com/hankeke/p/9971517.html
[BZOJ3669] [NOI2004] 魔法森林 LCT维护最小生成树相关推荐
- 洛谷 p2387 [noi2014] 膜fa♂森林 lct维护最小生成树
题目简述 做法 题目简述 求1-n的一条路径,路径上所有边的a的最大值和b的最大值相加最小. 做法 首先把边按照 a a a的大小排序,接下来用link_cut_tree维护1→n" rol ...
- [BZOJ3669]-[Noi2014]魔法森林-LCT+并查集
说在前面 刚刚去写了一道SPFA+网络流的糅合题,1A了 闲着没事干开始翻起了status,发现有人在做水管局长,哇这不是LCT嘛! 然后回头看了一下自己写过的寥寥无几的LCT的题,发现都快要忘了 于 ...
- [Luogu P2387] [NOI2014]魔法森林 (LCT维护边权)
题面 传送门:https://www.luogu.org/problemnew/show/P2387 Solution 这题的思想挺好的. 对于这种最大值最小类的问题,很自然的可以想到二分答案.很不幸 ...
- BZOJ 3669: [Noi2014]魔法森林( LCT )
排序搞掉一维, 然后就用LCT维护加边MST. O(NlogN) ------------------------------------------------------------------- ...
- loj2245 [NOI2014]魔法森林 LCT
[NOI2014]魔法森林 链接 loj 思路 a排序,b做动态最小生成树. 把边拆成点就可以了. uoj98.也许lct复杂度写假了..越卡常,越慢 代码 #include <bits/std ...
- [BZOJ]3669: [Noi2014]魔法森林 lct
Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M.初始时小E同学在号节 ...
- P4172 [WC2006]水管局长 LCT维护最小生成树
\(\color{#0066ff}{ 题目描述 }\) SC 省 MY 市有着庞大的地下水管网络,嘟嘟是 MY 市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的 ...
- NOI2014魔法森林--LCT
题意:求一条1->n的路径,使得路径上的MAXA+MAXB最小. 做法:以a值从小到大对边排序,动态加边,维护一个最小生成树就行了.如果两个端点不连通,则直接加上,否则就把这个环上b值最大的边删 ...
- [LCT动态树] [NOI2014]魔法森林,[ZJOI2018]历史
[NOI2014] 魔法森林 题目 按照aaa精灵从小到大排序 按顺序插入每一条边 加入第iii条边后的最小代价为a[i]a[i]a[i]加上从111到nnn的所有路径中最大bbb最小的路径代价 维护 ...
最新文章
- 【Lintcode】046.Majority Number
- 关于a标签的 href 与 onlick
- ipython notebook 中 wavefile, display, Audio的使用
- [css] 解释下 CSS sprites的原理和优缺点分别是什么
- poj2750 PottedFlower(线段树的环状操作)
- 微信公众平台开发教程第21篇-“可信网址”白名单
- 三星Galaxy Note 10渲染图曝光:前置打孔双摄+后置横排四摄
- php一次上传多张图片,html5 multiple的使用。
- axure7 地址选择_Axure教程:省市县三级联动选择(全国省市区数据)
- Java核心技术 卷I 基础知识 学习笔记(1)
- Eclipse+Maven搭建Wbe项目(1)
- 如何下载互联网上的所有网页
- 利用Gecco爬取(蚂蚁短租网)列表页数据
- Linux中的各种栈:进程栈 线程栈 内核栈 中断栈
- mysql 查看版本的几种方法
- 颜色的前世今生21·Lab编码系统
- OR-CAD CAPTURE学习笔记——ERROR(ORCAP-11010)
- 关于拨号上网的几种错误解决办法
- 管理会计报告和财务报告的区别
- fbx模型实现顶点偏移
热门文章
- Error loading WebappClassLoader解决方法
- SQL插入数据的方法
- LGD:涨点神器!旷视孙剑、张祥雨团队提出标签引导的自蒸馏技术,助力目标检测!...
- 热门项目:高精度图像分类全流程开发
- DBFace升级,模型仅1.3M的轻量级高精度人脸检测模型
- 干货 | 局部特征图像配准用于缺陷检测
- 大幅减少GPU显存占用:可逆残差网络(The Reversible Residual Network)
- Scrapy网络爬虫框架实际案例讲解,Python爬虫原来如此简单!
- 【Matplotlib】【Python】如何使用matplotlib绘制绘制随机生成的点--随机漫步详解
- CVPR 2021 | 姿态可控的语音驱动