题面

一开始看到这道题虽然知道是跟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);
}

最新文章

  1. Python元组
  2. 关于ajax载入窗口使用RedirectToAction在窗口显示的问题
  3. Unity手游之路&lt;二&gt;Java版服务端使用protostuff简化protobuf开发
  4. Python中用format函数格式化字符串的用法
  5. SQL行转列和列转行
  6. 【css】a:hover 设置上下边框在 ie6 和 ie7 下失效
  7. 高吞吐量的分布式发布订阅消息系统Kafka--安装及测试
  8. 20145210 《Java程序设计》第07周学习总结
  9. 一次zabbix的渗透
  10. 【莫队】bzoj 3781,bzoj 2038,bzoj 3289
  11. 礼仪或许就是尊重的还有一个说法——leo鉴书61
  12. OpenOffice 服务开机启动
  13. 那些年被我坑过的Python——不得不知(第二章)
  14. PHP 中filter_var的使用
  15. 使用MD5完成自定义Person对象的加密过程
  16. Composite Design Pattern 设计模式组合
  17. redis7--hash set的操作
  18. 绘图——Android绘图基础:Canvas、Paint等
  19. table 表格的增删和修改
  20. JProfiler简明使用教程

热门文章

  1. Linux下安装Tomcat(2)
  2. s6tu
  3. 如何修改运行中的docker容器的端口映射
  4. 【CDN+】Kafka 的初步认识与入门
  5. cron 定时任两种配置方式
  6. ab工具进行压力测试
  7. Redux生态系统
  8. 牛客 打印N个数组整体最大的Top K
  9. 跨域资源共享(CORS)-漏洞整理
  10. Eclipse常见版本和JDK常用版本对应关系