题面

一开始看到这道题虽然知道是跟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维护最小生成树相关推荐

  1. 洛谷 p2387 [noi2014] 膜fa♂森林 lct维护最小生成树

    题目简述 做法 题目简述 求1-n的一条路径,路径上所有边的a的最大值和b的最大值相加最小. 做法 首先把边按照 a a a的大小排序,接下来用link_cut_tree维护1→n" rol ...

  2. [BZOJ3669]-[Noi2014]魔法森林-LCT+并查集

    说在前面 刚刚去写了一道SPFA+网络流的糅合题,1A了 闲着没事干开始翻起了status,发现有人在做水管局长,哇这不是LCT嘛! 然后回头看了一下自己写过的寥寥无几的LCT的题,发现都快要忘了 于 ...

  3. [Luogu P2387] [NOI2014]魔法森林 (LCT维护边权)

    题面 传送门:https://www.luogu.org/problemnew/show/P2387 Solution 这题的思想挺好的. 对于这种最大值最小类的问题,很自然的可以想到二分答案.很不幸 ...

  4. BZOJ 3669: [Noi2014]魔法森林( LCT )

    排序搞掉一维, 然后就用LCT维护加边MST. O(NlogN) ------------------------------------------------------------------- ...

  5. loj2245 [NOI2014]魔法森林 LCT

    [NOI2014]魔法森林 链接 loj 思路 a排序,b做动态最小生成树. 把边拆成点就可以了. uoj98.也许lct复杂度写假了..越卡常,越慢 代码 #include <bits/std ...

  6. [BZOJ]3669: [Noi2014]魔法森林 lct

    Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M.初始时小E同学在号节 ...

  7. P4172 [WC2006]水管局长 LCT维护最小生成树

    \(\color{#0066ff}{ 题目描述 }\) SC 省 MY 市有着庞大的地下水管网络,嘟嘟是 MY 市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的 ...

  8. NOI2014魔法森林--LCT

    题意:求一条1->n的路径,使得路径上的MAXA+MAXB最小. 做法:以a值从小到大对边排序,动态加边,维护一个最小生成树就行了.如果两个端点不连通,则直接加上,否则就把这个环上b值最大的边删 ...

  9. [LCT动态树] [NOI2014]魔法森林,[ZJOI2018]历史

    [NOI2014] 魔法森林 题目 按照aaa精灵从小到大排序 按顺序插入每一条边 加入第iii条边后的最小代价为a[i]a[i]a[i]加上从111到nnn的所有路径中最大bbb最小的路径代价 维护 ...

最新文章

  1. 【Lintcode】046.Majority Number
  2. 关于a标签的 href 与 onlick
  3. ipython notebook 中 wavefile, display, Audio的使用
  4. [css] 解释下 CSS sprites的原理和优缺点分别是什么
  5. poj2750 PottedFlower(线段树的环状操作)
  6. 微信公众平台开发教程第21篇-“可信网址”白名单
  7. 三星Galaxy Note 10渲染图曝光:前置打孔双摄+后置横排四摄
  8. php一次上传多张图片,html5 multiple的使用。
  9. axure7 地址选择_Axure教程:省市县三级联动选择(全国省市区数据)
  10. Java核心技术 卷I 基础知识 学习笔记(1)
  11. Eclipse+Maven搭建Wbe项目(1)
  12. 如何下载互联网上的所有网页
  13. 利用Gecco爬取(蚂蚁短租网)列表页数据
  14. Linux中的各种栈:进程栈 线程栈 内核栈 中断栈
  15. mysql 查看版本的几种方法
  16. 颜色的前世今生21·Lab编码系统
  17. OR-CAD CAPTURE学习笔记——ERROR(ORCAP-11010)
  18. 关于拨号上网的几种错误解决办法
  19. 管理会计报告和财务报告的区别
  20. fbx模型实现顶点偏移

热门文章

  1. Error loading WebappClassLoader解决方法
  2. SQL插入数据的方法
  3. LGD:涨点神器!旷视孙剑、张祥雨团队提出标签引导的自蒸馏技术,助力目标检测!...
  4. 热门项目:高精度图像分类全流程开发
  5. DBFace升级,模型仅1.3M的轻量级高精度人脸检测模型
  6. 干货 | 局部特征图像配准用于缺陷检测
  7. 大幅减少GPU显存占用:可逆残差网络(The Reversible Residual Network)
  8. Scrapy网络爬虫框架实际案例讲解,Python爬虫原来如此简单!
  9. 【Matplotlib】【Python】如何使用matplotlib绘制绘制随机生成的点--随机漫步详解
  10. CVPR 2021 | 姿态可控的语音驱动