luogu P2387 [NOI2014]魔法森林
这题似乎不好直接做,可以考虑按照\(a_i\)升序排序,然后依次加边更新答案
具体实现方法是用lct维护当前的树,这里需要维护链上最大的\(b_i\).每次加一条边,如果加完以后没有环直接加,否则找出链上最大的\(b_i\),如果这个\(b_i\)比当前的\(b_i\)小,加了肯定不优,否则就把那条边断掉,加上这条边.每次用当前\(a_i\)和1到n链上最大\(b_i\)更新答案
#include<bits/stdc++.h>
#define LL long long
#define db long double
#define il inline
using namespace std;
const int N=1e5+10;
il LL rd()
{
LL x=0,w=1;char ch=0;
while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int n,m,w[N],po[N][2],tt;
int fa[N],ch[N][2],id[N],vi[N];
bool tg[N];
bool nrt(int x){return ch[fa[x]][0]==x||ch[fa[x]][1]==x;}
void psup(int x)
{
id[x]=w[id[ch[x][0]]]>w[id[ch[x][1]]]?id[ch[x][0]]:id[ch[x][1]];
id[x]=w[id[x]]>w[vi[x]]?id[x]:vi[x];
}
void rev(int x){if(x) swap(ch[x][0],ch[x][1]),tg[x]^=1;}
void psdn(int x){if(tg[x]) rev(ch[x][0]),rev(ch[x][1]),tg[x]=0;}
void ppush(int x)
{
if(nrt(x)) ppush(fa[x]);
psdn(x);
}
void rot(int x)
{
int y=fa[x],z=fa[y],yy=ch[y][1]==x,w=ch[x][!yy];
if(nrt(y)) ch[z][ch[z][1]==y]=x;
ch[y][yy]=w,ch[x][!yy]=y;
if(w) fa[w]=y;
fa[x]=z,fa[y]=x;
psup(y);
}
void spl(int x)
{
ppush(x);
while(nrt(x))
{
int y=fa[x];
if(nrt(y)) ((ch[y][1]==x)^(ch[fa[y]][1]==y))?rot(x):rot(y);
rot(x);
}
psup(x);
}
void acs(int x)
{
for(int y=0;x;y=x,x=fa[x])
spl(x),ch[x][1]=y,psup(x);
}
void mkrt(int x)
{
acs(x),spl(x),rev(x);
}
int fdrt(int x)
{
acs(x),spl(x);
psdn(x);
while(ch[x][0]) x=ch[x][0],psdn(x);
return x;
}
void split(int x,int y)
{
mkrt(x),acs(y),spl(y);
}
void link(int x,int y,int z)
{
mkrt(x);
if(fdrt(y)!=x)
{
mkrt(y);
w[++tt]=z,vi[tt]=tt,po[tt][0]=x,po[tt][1]=y;
fa[x]=fa[y]=tt;
return;
}
acs(y),spl(y);
int ii=id[y];
if(w[ii]<=z) return;
mkrt(po[ii][0]),acs(po[ii][1]),spl(ii);
fa[po[ii][0]]=fa[po[ii][1]]=ch[ii][0]=ch[ii][1]=0,psup(ii);
w[ii]=z,po[ii][0]=x,po[ii][1]=y;
mkrt(x),mkrt(y);
fa[x]=fa[y]=ii;
}
struct edge
{
int x,y,a,b;
bool operator < (const edge &bb) const {return a<bb.a;}
}e[N];
int main()
{
n=rd(),m=rd();
for(int i=1;i<=m;++i)
{
int x=rd(),y=rd(),a=rd(),b=rd();
e[i]=(edge){x,y,a,b};
}
sort(e+1,e+m+1);
tt=n,w[0]=-(1<<30);
int ans=1<<30;
for(int i=1;i<=m;++i)
{
if(e[i].x==e[i].y) continue;
link(e[i].x,e[i].y,e[i].b);
mkrt(1);
if(fdrt(n)==1) ans=min(ans,e[i].a+w[id[n]]);
}
printf("%d\n",ans<(1<<29)?ans:-1);
return 0;
}
luogu P2387 [NOI2014]魔法森林的更多相关文章
- [Luogu P2387] [NOI2014]魔法森林 (LCT维护边权)
题面 传送门:https://www.luogu.org/problemnew/show/P2387 Solution 这题的思想挺好的. 对于这种最大值最小类的问题,很自然的可以想到二分答案.很不幸 ...
- P2387 [NOI2014]魔法森林(LCT)
P2387 [NOI2014]魔法森林 LCT边权维护经典题 咋维护呢?边化为点,边权变点权. 本题中我们把边对关键字A进行排序,动态维护关键字B的最小生成树 加边后出现环咋办? splay维护最大边 ...
- 洛谷 P2387 [NOI2014]魔法森林 解题报告
P2387 [NOI2014]魔法森林 题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2 ...
- 洛谷P2387 [NOI2014]魔法森林(lct维护最小生成树)
题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2,3,…,n,边标号为 1,2,3,…, ...
- P2387 [NOI2014]魔法森林 LCT维护最小生成树
\(\color{#0066ff}{ 题目描述 }\) 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 ...
- 洛谷P2387 [NOI2014]魔法森林(LCT)
魔法森林 题目传送门 解题思路 把每条路按照\(a\)的值从小到大排序.然后用LCT按照b的值维护最小生成树,将边按照顺序放入.如果\(1\)到\(n\)有了一条路径,就更新最小答案.这个过程就相当于 ...
- 洛谷P2387 [NOI2014]魔法森林(LCT,Splay)
在XZY&XZZ巨佬的引领下,一枚蒟蒻终于啃动了这道题...... 这次还是第一次写LCT维护边权,还要化边为点,思路乱七八糟的,写起来也不顺手,还好调了许久终于AC啦. 贪心排序按一个关键字 ...
- 洛谷P2387 [NOI2014]魔法森林(LCT)
在XZY&XZZ巨佬的引领下,一枚蒟蒻终于啃动了这道题...... 这次还是第一次写LCT维护边权,还要化边为点,思路乱七八糟的,写起来也不顺手,还好调了许久终于AC啦. 贪心排序按一个关键字 ...
- P2387 [NOI2014]魔法森林
传送门 如果一条边只要考虑 $a$ 的限制,那么显然最小生成树 但是现在有 $a,b$ 两个限制,所以考虑按 $a$ 从小到大枚举边,动态维护 $b$ 的最小生成树 考虑新加入的一条边 $x,y$ , ...
随机推荐
- golang语言并发与并行——goroutine和channel的详细理解(一)
如果不是我对真正并行的线程的追求,就不会认识到Go有多么的迷人. Go语言从语言层面上就支持了并发,这与其他语言大不一样,不像以前我们要用Thread库 来新建线程,还要用线程安全的队列库来共享数据. ...
- c# WebApi之身份验证:Basic基础认证
为什么需要身份认证 身份认证是为了提高接口访问的安全性,如果没有身份验证,那么任何匿名用户只要知道服务器的url,就可以随意访问服务器,从而访问或者操作数据库,这会是很恐怖的事. 什么是Basic基础 ...
- react-native中的scrollables
这是一个点击切换的demo 先看效果 然后看实现的代码 import React from 'react'; import { Text, View } from 'react-native'; im ...
- SNP在世界地图上的频率分布
简单介绍两个网页工具,第一个是GGV,其界面如下: 第二个工具是HGDP,个人感觉画出来有点丑..都是同一所大学开发出来的:界面如下:
- Vector使用测试
1.测试vector是否自动释放分配的空间 vector有大致两类申请空间的方式,一是vector(n,T()),一是vector(p,p+n)(p是自己申请的空间的指针). 其中第一种估计肯定会释放 ...
- C++基础知识--DAY1
1. C语言是面向过程的语言,C++是面向对象的语言,相对于C语言来说,C++语法规则更为严格,其存在类型增强的问题. 类型增强,顾名思义就是C++相对于C语言来说有更加严格的类型检查,很多C语言的语 ...
- POJ 1815 Friendship (Dinic)
Friendship Time Limit: 2000MS Memory Limit: 20000K Total Submissions: 11429 Accepted: 3173 Descr ...
- C++(3):./Encryptor: undefined symbol:Z11startserviceLAKJDFLJALDKJFLLLLL
在Linux下编译得Encryptor文件,但是执行./Encryptor时 报了如上错误:undefined symbol:Z11startserviceLAKJDFLJALDKJFLLLLL 原因 ...
- python要点简要-一日精通python
Python2.x是历史,Python3.x是这门语言的现在和未来.Python2和3大约90%的地方都很相似的. 1.注释 单行注释:在注释的前面输入#号,如下: # 这是一条注释 多行注释:使用三 ...
- python3 aes加解密
# encoding: utf-8 import xlrd import os import yaml import logging.config from Crypto.Cipher import ...