[bzoj] 3669 NOI2014 魔法森林 || LCT
原题
copy一篇题解:原链接
将边按照a排序,然后从小到大枚举,加入图中。
在图中用lct维护一棵两点之间b最大值尽量小的生成树。
当加入一条边(u, v)时:
如果(u, v)不连通,则直接加入这条边
如果(u, v)连通且它们间路径上的b最大值大于当前边的b,则删除路径上b最大的边,然后加入当前边。
否则这条边没用。
AC代码:
#include<cstdio>
#include<algorithm>
#define N 150010
#define M 100010
#define inf 0x3f3f3f3f
#define which(u) (ls[fa[(u)]]==(u))
#define isroot(u) (!fa[(u)] || (ls[fa[(u)]]!=(u) && rs[fa[u]]!=(u)))
using namespace std;
int n,m,fa[N],ls[N],rs[N],a[N],val[N],ans=inf,num[N],pcnt;
bool rev[N];
char s[20];
struct hhh
{
    int u,v,a,b,p;
    bool operator < (const hhh &qwq) const
	{
	    if (a==qwq.a) return b<qwq.b;
	    return a<qwq.a;
	}
}e[M];
int Max(int a,int b)
{
    return e[a].b>e[b].b?a:b;
}
void update(int x)
{
    val[x]=Max(Max(val[ls[x]],val[rs[x]]),num[x]);
}
void rotate(int u)
{
    int v=fa[u],w=fa[v],b=which(u)?rs[u]:ls[u];
    if (!isroot(v)) (which(v)?ls[w]:rs[w])=u;
    which(u)?(ls[v]=b,rs[u]=v):(rs[v]=b,ls[u]=v);
    fa[u]=w,fa[v]=u;
    if (b) fa[b]=v;
    update(v);
}
void pushdown(int u)
{
    if (!rev[u]) return ;
    rev[ls[u]]^=1;
    rev[rs[u]]^=1;
    swap(ls[u],rs[u]);
    rev[u]=0;
}
void splay(int u)
{
    static int stk[N],top;
    stk[top=1]=u;
    while (!isroot(stk[top])) stk[top+1]=fa[stk[top]],top++;
    while (top) pushdown(stk[top--]);
    while (!isroot(u))
    {
	if (!isroot(fa[u]))
	{
	    if (which(u)==which(fa[u])) rotate(fa[u]);
	    else rotate(u);
	}
	rotate(u);
    }
    update(u);
}
void access(int u)
{
    int v=0;
    while (u)
    {
	splay(u);
	rs[u]=v;
	v=u;
	u=fa[u];
    }
}
void makeroot(int u)
{
    access(u);
    splay(u);
    rev[u]^=1;
}
int findroot(int x)
{
    access(x);
    splay(x);
    while (pushdown(x),ls[x]) x=ls[x];
    splay(x);
    return x;
}
void link(int u,int v)
{
    makeroot(v);
    fa[v]=u;
}
void cut(int u,int v)
{
    makeroot(u);
    access(v);
    splay(v);
    ls[v]=fa[u]=0;
    update(v);
}
void add(int i)
{
    e[i].p=++pcnt;
    num[e[i].p]=val[e[i].p]=i;
    link(e[i].u,e[i].p);
    link(e[i].v,e[i].p);
}
void erase(int i)
{
    cut(e[i].u,e[i].p);
    cut(e[i].v,e[i].p);
}
int query(int u,int v)
{
    makeroot(u);
    access(v);
    splay(v);
    return val[v];
}
int main()
{
    scanf("%d%d",&n,&m);
    pcnt=n;
    for (int i=1;i<=m;i++)
	scanf("%d%d%d%d",&e[i].u,&e[i].v,&e[i].a,&e[i].b);
    sort(e+1,e+m+1);
    for (int i=1;i<=m;i++)
    {
	if (findroot(e[i].u)!=findroot(e[i].v)) add(i);
	else
	{
	    int mx=query(e[i].u,e[i].v);
	    if (e[mx].b>e[i].b)
		erase(mx),add(i);
	}
	if (findroot(1)==findroot(n))
	    ans=min(ans,e[i].a+e[query(1,n)].b);
    }
    printf("%d",ans!=inf?ans:-1);
    return 0;
}
												
											[bzoj] 3669 NOI2014 魔法森林 || LCT的更多相关文章
- BZOJ 3669: [Noi2014]魔法森林( LCT )
		
排序搞掉一维, 然后就用LCT维护加边MST. O(NlogN) ------------------------------------------------------------------- ...
 - bzoj 3669: [Noi2014]魔法森林 (LCT)
		
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3669 题面: 3669: [Noi2014]魔法森林 Time Limit: 30 Sec ...
 - bzoj 3669: [Noi2014] 魔法森林 LCT版
		
Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M.初始时小E同学在号节 ...
 - BZOJ 3669: [Noi2014]魔法森林 [LCT Kruskal | SPFA]
		
题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2,3,…,n,边标号为 1,2,3,…, ...
 - BZOJ 3669: [Noi2014]魔法森林(lct+最小生成树)
		
传送门 解题思路 \(lct\)维护最小生成树.我们首先按照\(a\)排序,然后每次加入一条边,在图中维护一棵最小生成树.用并查集判断一下\(1\)与\(n\)是否联通,如果联通的话就尝试更新答案. ...
 - bzoj 3669: [Noi2014]魔法森林
		
bzoj 3669: [Noi2014]魔法森林 Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号 ...
 - bzoj 3669: [Noi2014]魔法森林 动态树
		
3669: [Noi2014]魔法森林 Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 363 Solved: 202[Submit][Status] ...
 - bzoj 3669: [Noi2014]魔法森林  -- 动点spfa
		
3669: [Noi2014]魔法森林 Time Limit: 30 Sec Memory Limit: 512 MB 动点spfa Description 为了得到书法大家的真传,小E同学下定决心 ...
 - [BZOJ 3669] [Noi2014] 魔法森林 【LCT】
		
题目链接:BZOJ - 3669 题目分析 如果确定了带 x 只精灵A,那么我们就是要找一条 1 到 n 的路径,满足只经过 Ai <= x 的边,而且要使经过的边中最大的 Bi 尽量小. 其实 ...
 - bzoj 3669: [Noi2014]魔法森林(并查集+LCT)
		
Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M.初始时小E同学在号节 ...
 
随机推荐
- 通过 Python_Faker 生成测试数据
			
通过 Python_Faker 生成测试数据 一.介绍 在软件需求.开发.测试过程中,有时候需要使用一些测试数据,针对这种情况,我们一般要么使用已有的系统数据,你不可能通过手工来生成(最傻的方法)可能 ...
 - 安装mysql-5.7.12-winx64
			
之前安装mysql时未做总结,换新电脑,补上安装记录,安装的时候,找了些网友的安装记录,发现好多坑 1.mysql-5.7.12-winx64.zip下载 官方下载地址:http://dev.mysq ...
 - 在Unity中使用LitJson解析json文件
			
LitJson 这个库需要找资源,找到LitJson.dll后将它放在Assets文件夹下,在脚本中使用using引入即可 测试代码 json文件: {"Archice":[{&q ...
 - sqlserver错误126解决方法
			
是不是很尴尬! 华丽的分割线下便是解决方法: 1.打开sqlserver配置管理器. 2.选择sqlserver网络配置,并禁用VIA协议确定保存. 3.在服务里面启动[SQL Server (SQL ...
 - LabVIEW初篇---前言
			
最早接触labview,是研二的时候,2007年,当时为了补贴家用,改善生活.自己拿着本科毕业证去找工作,去一个企业面试,当时,面试的主考官,问了会什么吗,比如PLC.单片机啥的?那时候的自己,基本上 ...
 - * 197. Permutation Index【LintCode by java】
			
Description Given a permutation which contains no repeated number, find its index in all the permuta ...
 - 凸包算法(Graham扫描法)详解
			
先说下基础知识,不然不好理解后面的东西 两向量的X乘p1(x1,y1),p2(x2,y2) p1Xp2如果小于零则说明 p1在p2的逆时针方向 如果大于零则说明 p1在p2的顺时针方向 struct ...
 - spark-shell解析
			
spark-shell 作用: 调用spark-submit脚本,如下参数 --classorg.apache.spark.repl.Main --name "Spark shell&quo ...
 - HTML5+Bootstrap 学习笔记 1
			
HTML <header> 标签 <header> 标签定义文档的页眉(介绍信息),是 HTML 5 中的新标签. 参考资料: HTML <header> 标签 h ...
 - Java 继承和访问控制
			
类的继承 Java中使用extends来实现继承 通过继承,子类自动拥有了基类(supercalss)的所有成员. Java只支持单继承,一个子类只允许有一个基类,一个基类可以有多个子类. class ...