这道题看题意是在求一个二维最小瓶颈路,唯一可行方案就是枚举一维在这一维满足的条件下使另一维最小,那么我们就把第一维排序利用A小的边在A大的情况下仍成立来动态加边维护最小生成树。

#include <cstdio>
#include <algorithm>
namespace Pre{
inline void read(int &sum){
register char ch=getchar();
for(sum=;ch<''||ch>'';ch=getchar());
for(;ch>=''&&ch<='';sum=(sum<<)+(sum<<)+ch-'',ch=getchar());
}
const int N=;
const int M=;
const int Inf=0x7f7f7f7f;
int A[M],B[M],ans=Inf,X[M],Y[M],n,m,e[M];
inline bool comp(int a,int b){
return A[a]<A[b];
}
inline int Max(int x,int y){
return x>y?x:y;
}
inline int Min(int x,int y){
return x<y?x:y;
}
}
namespace LCT{
const int MN=;
struct Node{
Node *ch[],*f;
int id,rid;
bool rev;
inline void pushup(){
using Pre::B;
id=B[ch[]->id]>B[ch[]->id]?ch[]->id:ch[]->id;
id=B[id]>B[rid]?id:rid;
}
inline void pushdown();
}null[MN];
inline void Swap(Node *&a,Node *&b){
Node *c=a;
a=b;
b=c;
}
inline void Node:: pushdown(){
if(!rev)return;
Swap(ch[],ch[]);
ch[]->rev^=;
ch[]->rev^=;
rev=;
}
inline void Init(){
using namespace Pre;
null->ch[]=null->ch[]=null->f=null;
for(int i=;i<=n;i++)
null[i].ch[]=null[i].ch[]=null[i].f=null,null[i].id=null[i].rid=;
for(int i=n+;i<=n+m;i++)
null[i].ch[]=null[i].ch[]=null[i].f=null,null[i].id=null[i].rid=i-n;
}
inline int get(Node *p){
return p->f->ch[]==p;
}
inline bool isroot(Node *p){
return p->f->ch[]!=p&&p->f->ch[]!=p;
}
inline void rotate(Node *p){
Node *fa=p->f,*pa=fa->f;
int j=get(p);
if(!isroot(fa))pa->ch[get(fa)]=p;
if((fa->ch[j]=p->ch[j^])!=null)fa->ch[j]->f=fa;
fa->f=p;
p->ch[j^]=fa;
p->f=pa;
fa->pushup();
p->pushup();
}
inline void spaly(Node *p){
p->pushdown();
for(Node *fa=p->f;!isroot(p);rotate(p),fa=p->f)
if(!isroot(fa)){
fa->f->pushdown(),fa->pushdown(),p->pushdown();
rotate(get(fa)==get(p)?fa:p);
}else
fa->pushdown(),p->pushdown();
}
inline void expose(Node *p){
Node *y=null;
while(p!=null){
spaly(p);
p->ch[]=y;
p->pushup();
y=p;
p=p->f;
}
}
inline void make_root(Node *p){
expose(p);
spaly(p);
p->rev^=;
}
inline Node *find_root(Node *p){
expose(p);
spaly(p);
while(p->ch[]!=null)
p=p->ch[],p->pushdown();
return p;
}
inline void link(Node *a,Node *b){
make_root(a);
a->f=b;
}
inline void cut(Node *a,Node *b){
make_root(a);
expose(b);
spaly(b);
b->ch[]->f=null;
b->ch[]=null;
b->pushup();
}
inline void Link(int a,int b){
link(null+a,null+b);
}
inline void Cut(int a,int b){
cut(null+a,null+b);
}
inline int find(int x){
return find_root(null+x)-null;
}
inline int query(int a,int b){
Node *x=null+a,*y=null+b;
make_root(x);
expose(y);
spaly(y);
return Pre::B[y->id];
}
inline int query_id(int a,int b){
Node *x=null+a,*y=null+b;
make_root(x);
expose(y);
spaly(y);
return y->id;
}
}
inline void Init(){
using namespace Pre;
read(n),read(m);
for(int i=;i<=m;i++)
read(X[i]),read(Y[i]),read(A[i]),read(B[i]),e[i]=i;
std::sort(e+,e+m+,comp);
LCT::Init();
}
inline void Work(){
using namespace Pre;
using LCT::find;
using LCT::query;
using LCT::Link;
using LCT::Cut;
using LCT::query_id;
for(int i=;i<=m;i++)
if(find(X[e[i]])!=find(Y[e[i]])){
Link(e[i]+n,X[e[i]]),Link(e[i]+n,Y[e[i]]);
if(find()==find(n))
ans=Min(query(,n)+A[e[i]],ans);
}else if(query(X[e[i]],Y[e[i]])>B[e[i]]){
int temp=query_id(X[e[i]],Y[e[i]]);
Cut(temp+n,X[temp]),Cut(temp+n,Y[temp]);
Link(e[i]+n,X[e[i]]),Link(e[i]+n,Y[e[i]]);
if(find()==find(n))
ans=Min(ans,query(,n)+A[e[i]]);
}
}
int main(){
using namespace Pre;
Init(),Work();
printf("%d",ans==Inf?-:ans);
return ;
}

【BZOJ 3669】 [Noi2014]魔法森林 LCT维护动态最小生成树的更多相关文章

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

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

  2. bzoj 3669: [Noi2014]魔法森林 (LCT)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3669 题面: 3669: [Noi2014]魔法森林 Time Limit: 30 Sec  ...

  3. bzoj 3669: [Noi2014] 魔法森林 LCT版

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

  4. BZOJ 3669: [Noi2014]魔法森林 [LCT Kruskal | SPFA]

    题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2,3,…,n,边标号为 1,2,3,…, ...

  5. BZOJ 3669: [Noi2014]魔法森林(lct+最小生成树)

    传送门 解题思路 \(lct\)维护最小生成树.我们首先按照\(a\)排序,然后每次加入一条边,在图中维护一棵最小生成树.用并查集判断一下\(1\)与\(n\)是否联通,如果联通的话就尝试更新答案. ...

  6. bzoj 3669: [Noi2014]魔法森林

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

  7. bzoj 3669: [Noi2014]魔法森林 动态树

    3669: [Noi2014]魔法森林 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 363  Solved: 202[Submit][Status] ...

  8. bzoj 3669: [Noi2014]魔法森林 -- 动点spfa

    3669: [Noi2014]魔法森林 Time Limit: 30 Sec  Memory Limit: 512 MB 动点spfa Description 为了得到书法大家的真传,小E同学下定决心 ...

  9. [BZOJ 3669] [Noi2014] 魔法森林 【LCT】

    题目链接:BZOJ - 3669 题目分析 如果确定了带 x 只精灵A,那么我们就是要找一条 1 到 n 的路径,满足只经过 Ai <= x 的边,而且要使经过的边中最大的 Bi 尽量小. 其实 ...

随机推荐

  1. scrapy框架爬取笔趣阁

    笔趣阁是很好爬的网站了,这里简单爬取了全部小说链接和每本的全部章节链接,还想爬取章节内容在biquge.py里在加一个爬取循环,在pipelines.py添加保存函数即可 1 创建一个scrapy项目 ...

  2. Redis缓存数据库的安装与配置(3)

    3 Redis主动同步设置方法 Redis主从同步 1.Redis主从同步特点 一个master可以拥有多个slave 多个slave可以连接同一个master,还可以连接到其他slave 主从复制不 ...

  3. Node.js中的不安全跳转如何防御详解

    Node.js中的不安全跳转如何防御详解 导语: 早年在浏览器大战期间,有远见的Chrome认为要运行现代Web应用,浏览器必须有一个性能非常强劲的Java引擎,于是Google自己开发了一个高性能的 ...

  4. C语言实例解析精粹学习笔记——35(报数游戏)

    实例35: 设由n个人站成一圈,分别被编号1,2,3,4,……,n.第一个人从1开始报数,每报数位m的人被从圈中推测,其后的人再次从1开始报数,重复上述过程,直至所有人都从圈中退出. 实例解析: 用链 ...

  5. class实现Stack

    基于class实现一个存储string类型的Stack 头文件: //stack.h #include<vector> #include<string> class Stack ...

  6. 4 echo服务器

    收到数据,给别人原封不动返回 #4. 将接收到的数据再发送给对方   udpSocket.sendto(recvData[0], recvData[1]) #coding=utf-8 from soc ...

  7. P1794 装备运输_NOI导刊2010提高(04)

    P1794 装备运输_NOI导刊2010提高(04) 题目描述 德国放松对英国的进攻后,把矛头指向了东边——苏联.1943年初,东线的战斗进行到白热化阶段.据可靠情报,90余万德国军队在库尔斯克准备发 ...

  8. 6.JAVA知识点归纳整理

    一.jdk初识与HelloWord: 二.java基础: 2.1 标识符_关键字_数据类型 2.2 数据类型转换 2.3 程序编写格式 2.4 运算符 2.5 分支与for循环 2.6 while_b ...

  9. Java并发基础--线程安全

    一.线程安全 1.线程安全的概念 线程安全:某个类被单个线程,或者多个线程同时访问,所表现出来的行为是一致,则可以说这个类是线程安全的. 2.什么情况下会出现线程安全问题 在单线程中不会出现线程安全问 ...

  10. [P2387魔法森林

    题面 题意: 给出一个图,边权有两维,a与b. 求1到n的一条路径使得路径经过的边的最大的a与b的和最小,输出最小之和. \(Solution:\) 如果做过这题,那么就显得很简单了很好想了. 又是想 ...