题目描述

  给你一个\(n\)个点\(m\)条边的图,每条边有两个边权\(a,b\)。请你找出从\(1\)到\(n\)一条路径,使得这条路径上边权\(a\)的最大值\(+\)边权\(b\)的最大值最小。

  \(n\leq 50000,m\leq 100000\)

题解

  我们可以考虑求出当边权\(a\leq\)某个数时边权\(b\)的最大值。

  先把边按边权\(a\)从小到大排序,依次加入,用LCT维护当前边权\(b\)的最小生成树。如果这两个点已经联通,就判断这两个点路径上边的边权\(b\)的最大值,如果大于当前这条边的边权\(b\),就把这条边删掉。否则就不加入这条边。

  每加完一条边我们就可以认为从\(1\)到\(n\)的边权\(a\)的最大值为当前这条边的边权\(a\)(否则就会在之前更新到),然后查询\(1\)到\(n\)的边权\(b\)的最大值,更新答案。

  时间复杂度:\(O(m\log n)\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
namespace lct
{
int a[200010][2];
int f[200010];
pii v[200010];
pii s[200010];
int r[200010];
int root(int x)
{
return !f[x]||(a[f[x]][0]!=x&&a[f[x]][1]!=x);
}
void reverse(int x)
{
swap(a[x][0],a[x][1]);
r[x]^=1;
}
void push(int x)
{
if(r[x])
{
if(a[x][0])
reverse(a[x][0]);
if(a[x][1])
reverse(a[x][1]);
r[x]=0;
}
}
void mt(int x)
{
s[x]=max(v[x],max(s[a[x][0]],s[a[x][1]]));
}
void rotate(int x)
{
if(root(x))
return;
int p=f[x];
int q=f[p];
int ps=(x==a[p][1]);
int qs=(p==a[q][1]);
int ch=a[x][ps^1];
if(!root(p))
a[q][qs]=x;
a[x][ps^1]=p;
a[p][ps]=ch;
if(ch)
f[ch]=p;
f[p]=x;
f[x]=q;
mt(p);
mt(x);
}
void clear(int x)
{
if(!root(x))
clear(f[x]);
push(x);
}
void splay(int x)
{
clear(x);
int p,q;
while(!root(x))
{
p=f[x];
if(!root(p))
{
q=f[p];
if((p==a[q][1])==(x==a[p][1]))
rotate(p);
else
rotate(x);
}
rotate(x);
}
}
void access(int x)
{
int y=x,t=0;
while(x)
{
splay(x);
a[x][1]=t;
mt(x);
t=x;
x=f[x];
}
splay(y);
}
void change(int x)
{
access(x);
reverse(x);
}
int findroot(int x)
{
access(x);
while(a[x][0])
x=a[x][0];
splay(x);
return x;
}
pii query(int x,int y)
{
change(x);
access(y);
return s[y];
}
void link(int x,int y)
{
change(x);
f[x]=y;
}
void cut(int x,int y)
{
change(x);
access(y);
f[a[y][0]]=0;
a[y][0]=0;
mt(y);
}
}
struct edge
{
int x,y;
int a,b;
};
edge a[100010];
int cmp(edge a,edge b)
{
return a.a<b.a;
}
int main()
{
// freopen("bzoj3669.in","r",stdin);
// freopen("bzoj3669.out","w",stdout);
int n,m;
scanf("%d%d",&n,&m);
int i;
for(i=1;i<=m;i++)
scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].a,&a[i].b);
sort(a+1,a+m+1,cmp);
int ans=0x7fffffff;
for(i=1;i<=m;i++)
{
if(a[i].x==a[i].y)
continue;
if(lct::findroot(a[i].x)==lct::findroot(a[i].y))
{
pii s=lct::query(a[i].x,a[i].y);
if(a[i].b>=a[s.second].b)
continue;
lct::cut(s.second+n,a[s.second].x);
lct::cut(s.second+n,a[s.second].y);
}
lct::v[i+n]=pii(a[i].b,i);
lct::link(a[i].x,i+n);
lct::link(a[i].y,i+n);
if(lct::findroot(1)==lct::findroot(n))
ans=min(ans,a[i].a+lct::query(1,n).first);
}
if(ans==0x7fffffff)
ans=-1;
printf("%d\n",ans);
return 0;
}

【BZOJ3669】【NOI2014】魔法森林 LCT的更多相关文章

  1. bzoj3669: [Noi2014]魔法森林 lct版

    先上题目 bzoj3669: [Noi2014]魔法森林 这道题首先每一条边都有一个a,b 我们按a从小到大排序 每次将一条路劲入队 当然这道题权在边上 所以我们将边化为点去连接他的两个端点 当然某两 ...

  2. bzoj3669: [Noi2014]魔法森林 lct

    记得去年模拟赛的时候好像YY出二分答案枚举a,b的暴力,过了55欸 然后看正解,为了将两维变成一维,将a排序,模拟Kruskal的加边过程,同时维护1到n的最大值,加入一条边e(u,v,a,b)时有以 ...

  3. [bzoj3669][Noi2014]魔法森林——lct

    Brief description 给定一个无向图,求从1到n的一条路径使得这条路径上最大的a和b最小. Algorithm Design 以下内容选自某HN神犇的blog 双瓶颈的最小生成树的感觉, ...

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

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

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

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

  6. [NOI2014]魔法森林 LCT

    题面 [NOI2014]魔法森林 题解 一条路径的代价为路径上的\(max(a[i]) + max(b[i])\),因为一条边同时有$a[i], b[i]$2种权值,直接处理不好同时兼顾到,所以我们考 ...

  7. loj2245 [NOI2014]魔法森林 LCT

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

  8. 【BZOJ3669】[Noi2014]魔法森林 LCT

    终于不是裸的LCT了...然而一开始一眼看上去这是kruskal..不对,题目要求1->n的路径上的每个点的两个最大权值和最小,这样便可以用LCT来维护一个最小生成路(瞎编的...),先以a为关 ...

  9. BZOJ3669[Noi2014]魔法森林——kruskal+LCT

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

  10. BZOJ3669: [Noi2014]魔法森林(瓶颈生成树 LCT)

    Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 3558  Solved: 2283[Submit][Status][Discuss] Descript ...

随机推荐

  1. CentOS 7从Python 2.7升级至Python3.6.1

    引言: CentOS是目前最为流行的Linux服务器系统,其默认的Python 2.x,但是根据python社区的规划,在不久之后,整个社区将向Python3迁移,且将不在支持Python2, 那该如 ...

  2. 一个6亿的表a,一个3亿的表b,通过外间tid关联,你如何最快的查询出满足条件的第50000到第50200中的这200条数据记录

    1.如果A表TID是自增长,并且是连续的,B表的ID为索引 select * from a,b where a.tid = b.id and a.tid>500000 limit 200; 2. ...

  3. l^oo不可分的两个注意点

    1  不理解等一个等式 , 2.不理解为什么,一个可分的集合里面有不可数的子集?谢谢 1是 2.是可分集合里面每个元素 做中心后的一个开覆盖 所有0 1序列是和所有二进制小数   可以一一对应   而 ...

  4. Jmeter操作之跨线程组传递参数

    思路:将某一线程组内的变量通过“__setProperty”函数设置成jmeter的全局变量,在另一线程组中通过“__P”函数调用即可. 1.添加-后置处理器-BeanShell PostProces ...

  5. IdentityServer4【QuickStart】之使用ResourceOwnerPassword流程来保护API

    使用ResourceOwnerPassword流程来保护API OAuth2.0中的ResourceOwnerPassword授权流程允许一个客户端发送username和password到token服 ...

  6. Javascript与C#对变量的处理方式

      先来看一下Javascript的情况(下面所说的基本类型和简单类型是一个意思): Javascript中变量会存在两种情况,一种是基本类型的,一共有五种,有null.Bollean.undefin ...

  7. linux 安装ssh以及ssh用法与免密登录

    想要免费登录就是把本地机器的id_rsa_pub的内容放到远程服务器的authorized_keys里面 一.配置yum和hosts文件 配置hosts文件: 命令:vi /etc/hosts 在文件 ...

  8. Redis 安装学习

    Linux下下载安装redis https://redis.io/download tar -zvxf redisxxx cd redisxxxx make  ---进行安装 vim ~.bash_p ...

  9. MyCat数据库中间件 - 分库

    MyCat MyCat用于解耦分布式数据库与java,比如分库分表以后,需要查询某条数据时,需要java根据需要查的数据先计算去哪个库查,然而有了Mycat就不用自己计算怎么存储,怎么查询了.MyCa ...

  10. zabbix模板

    https://github.com/xm-y/zabbix-community-repos  https://monitoringartist.github.io/zabbix-searcher/