BZOJ 3669: [Noi2014]魔法森林(lct+最小生成树)
解题思路
\(lct\)维护最小生成树。我们首先按照\(a\)排序,然后每次加入一条边,在图中维护一棵最小生成树。用并查集判断一下\(1\)与\(n\)是否联通,如果联通的话就尝试更新答案。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int MAXN = 50005;
const int MAXM = 1000005;
inline int rd(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
int n,m,ans=1e9,F[MAXN],val[MAXN+MAXM],num;
int xx[MAXN+MAXM],yy[MAXN+MAXM];
struct Edge{
int x,y,a,b;
friend bool operator<(const Edge A,const Edge B){
return A.a<B.a;
}
}edge[MAXM];
int Find(int x){
if(x==F[x]) return x;
return F[x]=Find(F[x]);
}
namespace lct{
int fa[MAXN+MAXM],ch[MAXN+MAXM][2],Max[MAXN+MAXM];
bool tag[MAXN+MAXM];
inline void pushup(int x){
Max[x]=x;
if(val[Max[ch[x][0]]]>val[Max[x]]) Max[x]=Max[ch[x][0]];
if(val[Max[ch[x][1]]]>val[Max[x]]) Max[x]=Max[ch[x][1]];
}
inline void pushdown(int x){
if(tag[x]){
tag[x]^=1;swap(ch[x][0],ch[x][1]);
if(ch[x][0]) tag[ch[x][0]]^=1;
if(ch[x][1]) tag[ch[x][1]]^=1;
}
}
inline bool isroot(int x){
return (x!=ch[fa[x]][0] && x!=ch[fa[x]][1]);
}
inline bool check(int x){
return (x==ch[fa[x]][1]);
}
void pd(int x){
if(!isroot(x)) pd(fa[x]);pushdown(x);
}
inline void rotate(int x){
int y=fa[x],z=fa[y];bool chk=check(x);
if(!isroot(y)) ch[z][check(y)]=x;
ch[y][chk]=ch[x][chk^1];fa[ch[x][chk^1]]=y;
ch[x][chk^1]=y;fa[y]=x;fa[x]=z;pushup(y);pushup(x);
}
inline void splay(int x){
pd(x);
for(;!isroot(x);rotate(x))
if(!isroot(fa[x])) rotate(check(fa[x])==check(x)?fa[x]:x);
}
inline void access(int x){
for(int y=0;x;y=x,x=fa[x])
splay(x),ch[x][1]=y,pushup(x);
}
inline void makeroot(int x){
access(x);splay(x);tag[x]^=1;
}
inline void link(int x,int y){
makeroot(x);fa[x]=y;pushup(y);
}
inline void split(int x,int y){
makeroot(x);access(y);splay(x);
}
inline void cut(int x,int y){
makeroot(x);access(y);splay(y);
fa[x]=ch[y][0]=0;pushup(y);
}
}
int main(){
n=rd(),m=rd();int x,y,a,b,A,u,v;
for(int i=1;i<=n;i++) F[i]=i;num=n;
for(int i=1;i<=m;i++){
x=rd(),y=rd(),a=rd(),b=rd();
edge[i].x=x,edge[i].y=y,edge[i].a=a,edge[i].b=b;
}
sort(edge+1,edge+1+m);
for(int i=1;i<=m;i++){
A=edge[i].a;x=edge[i].x,y=edge[i].y;
u=Find(edge[i].x);v=Find(edge[i].y);
if(u!=v){
val[++num]=edge[i].b;lct::link(x,num);lct::link(num,y);
xx[num]=x;yy[num]=y;F[u]=v;
}
else {
lct::split(x,y);
if(val[lct::Max[x]]>edge[i].b) {
a=lct::Max[x];b=yy[lct::Max[x]];val[++num]=edge[i].b;
lct::cut(xx[lct::Max[x]],lct::Max[x]);lct::cut(a,b);
lct::link(x,num),lct::link(num,y);xx[num]=x;yy[num]=y;
}
}
if(Find(1)==Find(n)){
lct::split(1,n);
ans=min(ans,A+val[lct::Max[1]]);
}
}
if(ans!=1e9) printf("%d\n",ans);
else puts("-1");
return 0;
}
BZOJ 3669: [Noi2014]魔法森林(lct+最小生成树)的更多相关文章
- bzoj 3669: [Noi2014]魔法森林 (LCT)
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3669 题面: 3669: [Noi2014]魔法森林 Time Limit: 30 Sec ...
- BZOJ 3669: [Noi2014]魔法森林( LCT )
排序搞掉一维, 然后就用LCT维护加边MST. O(NlogN) ------------------------------------------------------------------- ...
- 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]魔法森林
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同学在号节 ...
随机推荐
- 前后端分离进行权限管理之后端API返回菜单及权限信息(三)
一.动态菜单API的生成 1.API #菜单信息 url(r'^menus$', views.MenuModelView.as_view({"get": "list&qu ...
- 友善之臂arm9、 smart210监控版本,烧写系统
第一次接触嵌入式开发,就拿210练手了,第一天折腾,先烧系统. 准备:板子,8GB或者以上的SD卡,网上找下minitools以及系统小红帽,Android或者ubuntu,debian都可以.[ub ...
- Kylin-2.6.2集群部署
1. 集群节点规划与说明 rzx1 all rzx2 query rzx3 query 说明: Kylin节点角色有三种: all: 包含query和job query: 查询节点 job: 工作节点 ...
- 管理mysql
要管理MySQL,可以使用可视化图形界面MySQL Workbench. MySQL Workbench可以用可视化的方式查询.创建和修改数据库表,但是,归根到底,MySQL Workbench是一个 ...
- Shell基础(三):使用for循环结构、使用while循环结构、基于case分支编写脚本、使用Shell函数、中断及退出
一.使用for循环结构 目标: 本案例要求编写一个Shell脚本chkhosts.sh,利用for循环来检测多个主机的存活状态,相关要求及说明如下: 1> 对192.168.4.0/24网段执行 ...
- Go语言中接口组合的实现方法
在Go语言中,可以在接口A中组合其它的一个或多个接口(如接口B.C),这种方式等价于在接口A中添加接口B.C中声明的方法. 代码如下: //接口中可以组合其它接口,这种方式等效于在接口中添加其它接口的 ...
- JS 变量 相关内容
JS变量按存储方式区分为哪些类型?: js变量按照存储方式分为两种类型:值类型 和 引用类型 1.值类型(基本类型): 布尔值(boolean) . null .undefined .数值(numbe ...
- web开发调用百度地图API + AK申请
web开发调用百度地图API + AK申请 要使用百度地图的API我们首先需要在我们的html页面引入js----`` 如何获取百度地图ak: 1.登陆百度地图开发者平台 2.注册百度开发者账号并登陆 ...
- 互斥锁Demo
#include <stdio.h> #include <pthread.h> pthread_t work1Id; pthread_t work2Id; ; ; pthrea ...
- 使用redis实现客户端和服务端token验证
实在是思维江化啊,没有想到可以给redis设置不同的key值来实现不同key值存储不同的value值,而一直想着给一个名为token的key值新增不同的数据,并设置过期时间,然而这样却不能新增只能做到 ...