(NOI2014)(bzoj3669)魔法森林
LCT裸题,不会的可以来这里看看。
步入正题,现将边按a排序,依次加入每一条边,同时维护路径上的最小生成树上的最大边权,如果两点不连通,就直接连通。
如果两点已经连通,就将该边与路径上较小的一条比较,选择小的那一条即可
统计答案时,如果1与n连通就求出路径上最大值与当前的a值相加,取最小的一个。
但边权不好处理,于是我们把X—>Y路径拆成X->Z->Y,将边权放在Z的点权上即可
下面是代码
#include<bits/stdc++.h>
using namespace std;
typedef int sign;
typedef long long ll;
#define For(i,a,b) for(register sign i=(sign)a;i<=(sign)b;++i)
#define Fordown(i,a,b) for(register sign i=(sign)a;i>=(sign)b;--i)
const int N=5e4+5,M=1e5+5;
bool cmax(sign &a,sign b){return (a<b)?a=b,1:0;}
bool cmin(sign &a,sign b){return (a>b)?a=b,1:0;}
template<typename T>T read()
{
T ans=0,f=1;
char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch-'0'),ch=getchar();
return ans*f;
}
void file()
{
#ifndef ONLINE_JUDGE
freopen("LCT.in","r",stdin);
freopen("LCT.out","w",stdout);
#endif
}
int n,m;
int ch[N+M][2],fa[N+M],rev[N+M],edge[N+M],bl[N+M];
struct node
{
int u,v,a,b;
inline void init(){u=v=a=b=0;}
bool operator < (const node &x)const
{return a<x.a;}
}e[M];
inline void push_up(int x)
{
if(e[bl[x]].b>=e[edge[ch[x][0]]].b&&e[bl[x]].b>=e[edge[ch[x][1]]].b)edge[x]=bl[x];
else if(e[edge[ch[x][0]]].b>=e[edge[ch[x][1]]].b)edge[x]=edge[ch[x][0]];
else edge[x]=edge[ch[x][1]];
}
inline void push_down(int x)
{
if(rev[x])
{
rev[ch[x][0]]^=1;
rev[ch[x][1]]^=1;
swap(ch[x][0],ch[x][1]);
rev[x]=0;
}
}
inline bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
inline bool get(int x){return x==ch[fa[x]][1];}
inline void rotate(int x)
{
int old=fa[x],oldfa=fa[old],o=get(x);
if(!isroot(old))ch[oldfa][get(old)]=x;
fa[x]=oldfa;fa[ch[x][o^1]]=old;fa[old]=x;
ch[old][o]=ch[x][o^1];ch[x][o^1]=old;
push_up(old);push_up(x);
}
const int inf=0x3f3f3f3f;
int l[N+M],ans=inf;
inline void splay(int x)
{
l[0]=0;
int y=x;
while(1)
{
l[++l[0]]=y;
if(isroot(y))break;
y=fa[y];
}
Fordown(i,l[0],1)push_down(l[i]);
while(!isroot(x))
{
if(!isroot(fa[x]))rotate(get(x)^get(fa[x])?x:fa[x]);
rotate(x);
}
}
inline void access(int x)
{
for(register int y=0;x;y=x,x=fa[x])
{
splay(x);ch[x][1]=y;push_up(x);
}
}
inline void makeroot(int x)
{
access(x);splay(x);rev[x]^=1;
}
inline int find(int x)
{
access(x);splay(x);
while(ch[x][0])x=ch[x][0];
return x;
}
inline void cut(int x,int y)
{
makeroot(x);
access(y);splay(y);
if(ch[y][0]==x)ch[y][0]=fa[x]=0;
}
inline void link(int x,int y)
{
makeroot(x);fa[x]=y;
}
inline void deal(int i)
{
int x=e[i].u,y=e[i].v;
if(find(x)^find(y))link(x,i+n),link(i+n,y);
else
{
makeroot(x);
access(y);splay(y);
if(e[edge[y]].b>e[i].b)
{
int t=edge[y];
cut(t+n,e[t].u);
cut(t+n,e[t].v);
link(i+n,e[i].u);
link(i+n,e[i].v);
}
}
}
inline void input()
{
n=read<int>();m=read<int>();
For(i,1,m)
{
e[i].u=read<int>();
e[i].v=read<int>();
e[i].a=read<int>();
e[i].b=read<int>();
}
}
inline int cal()
{
if(find(1)^find(n))return inf;
makeroot(1);
access(n);splay(n);
return e[edge[n]].b;
}
inline void work()
{
sort(e+1,e+m+1);
e[0].init();
For(i,1,m)edge[i+n]=bl[i+n]=i;
For(i,1,m)
{
deal(i);
while(e[i].a==e[i+1].a)++i,deal(i);
cmin(ans,cal()+e[i].a);
}
printf("%d\n",ans==inf?-1:ans);
}
int main()
{
file();
input();
work();
return 0;
}
(NOI2014)(bzoj3669)魔法森林的更多相关文章
- 【BZOJ3669】【Noi2014】魔法森林(Link-Cut Tree)
[BZOJ3669][Noi2014]魔法森林(Link-Cut Tree) 题面 题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n ...
- BZOJ-3669 魔法森林 Link-Cut-Tree
意识到背模版的重要性了,记住了原理和操作,然后手打模版残了..颓我时间...... 3669: [Noi2014]魔法森林 Time Limit: 30 Sec Memory Limit: 512 M ...
- BZOJ 3669 【NOI2014】 魔法森林
Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M.初始时小E同学在号节 ...
- 【NOI2014】魔法森林
为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为 1…n1…n,边标号为1…m1…m.初始时小E同学在 11 号节点,隐 ...
- [BZOJ3669]魔法森林
Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M.初始时小E同学在号节 ...
- 【NOI2014】魔法森林 - 动态加边SPFA
题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2,3,…,n,边标号为 1,2,3,…, ...
- 【BZOJ3669】【NOI2014】魔法森林 LCT
题目描述 给你一个\(n\)个点\(m\)条边的图,每条边有两个边权\(a,b\).请你找出从\(1\)到\(n\)一条路径,使得这条路径上边权\(a\)的最大值\(+\)边权\(b\)的最大值最小. ...
- bzoj3669【NOI2014】魔法森林
题面一道最短路好题…… 开始和喻队长讨论了一下,喻队长一眼切:枚举ai的上界MAX,每次把ai小于等于MAX的边加到图里,以bi为边权跑最短路. 但是,这样做是O(ai*m)的,妥妥TLE,于是我们想 ...
- 【BZOJ】【3669】【NOI2014】魔法森林
LCT动态维护MST LCT动态维护MST 我们可以枚举a,然后找从1到n的一条路径使得:这条路径上的b的最大值最小.这个路径肯定在MST上……所以枚举一遍所有的边,动态维护一个关于b值的MST即可. ...
- 3754. 【NOI2014】魔法森林(LCT)
Problem 给定一个\(n\)个结点,\(m\)条边的的无向图,每条边有两个权值\(ai,bi\). 现在从\(1\)出发,要到达\(n\),每次只能沿着\(ai\le A\)且\(bi\le B ...
随机推荐
- 设置ssh key后push为什么还要输入用户名和密码
$ git push Username for 'https://github.com': Password for 'https://Username@github.com': Counting o ...
- rpm yum apt-get redhat centos ubuntu
rpm是由红帽公司开发的软件包管理方式,使用rpm我们可以方便的进行软件的安装.查询.卸载.升级等工作.但是rpm软件包之间的依赖性问题往往会很繁琐,尤其是软件由多个rpm包组成时.Yum(全称为 Y ...
- 虚拟机上不能使用CUDA
虚拟机的显卡是虚拟的,不能使用CUDA(至少很难),搞了一天才晃过神来: lspci 查找目前主机的硬件配备 用 grep -i 进行大小写无关的搜索
- mfc 虚函数
知识点 类虚函数概念 类虚函数定义virtual 一.虚函数 简单地说,那些被virtual关键字修饰的成员函数,就是虚函数. 二.虚函数定义 定义:在某基类中声明为 virtual 并在一个或多个派 ...
- 【LG4248】[AHOI2013]差异
[LG4248][AHOI2013]差异 题面 洛谷 题解 后缀数组版做法戳我 我们将原串\(reverse\),根据后缀自动机的性质,两个后缀的\(lcp\)一定是我们在反串后两个前缀的\(lca\ ...
- RegExp,实现匹配合法时间(24小时制)的正则表达式
合法时间格式 00:00:00 - 23:59:59 格式分析:H + ":" + M + ":" + S H-分析: 00:00:00 - 09:5 ...
- 蓝牙inquiry流程之Inquiry Complete处理
inquiry流程一般持续有12s多,当inquiry完成的时候,设备端会上报一个Event: Inquiry Complete 上来,那协议栈是如何把这个事件上传到应用层的呢?本篇文章来分析一下其具 ...
- service手动实例化(new)导致类中的spring对象无法注入的问题解决
下面说的这个画横线的可能是错误的,因为我之前用controller继承父类的注解对象的时候成功了,所以可能这次的唯一原因就是 不该把本该从ioc容器中拿出的对象通过new的方式实例化,至于继承注解对象 ...
- 在 JS 对象中使用 . 和 [] 操作属性的区别
在 JS 对象中,调用属性一般有两种方法--点和中括号的方法. 例如 使用点方法 var obj = { name: "cedric" } console.log(obj.name ...
- Panorama——H5实现全景图片原理
前言 H5是怎么实现全景图片播放呢? 正文 全景图的基本原理即 "等距圆柱投影",这是一种将球体上的各个点投影到圆柱体的侧面上的一种投影方式,投影后再展开就是一张 2:1 的矩形图 ...