洛谷2387 BZOJ3669魔法森林题解
这道题被很多人用spfa水了过去,表示很。。。
其实spfa很好卡,这组数据可以卡掉大多数spfa
链接:密码:rjvk
这里讲一下LCT的做法
我们按照a将边排序,然后依次添加
每次加入时若两边没有联通,就直接加入,否则就
检查两边的路径中权值b最大的权值是多少,如果大于当前加入边的权值
就将该边删掉,然后将当前边加入
注意lct维护边权时需要用到拆点
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstring>
# include<cstdio>
using namespace std;
const int mn = ;
const int inf = ;
struct edge{int u,v,a,b;};
edge e[mn];
bool cmp(const edge &x,const edge &y)
{
if(x.a==y.a) return x.b<y.b;
else return x.a<y.a;
}
int n,m,ans,fa[mn];
int _find(int x) {return x==fa[x] ? x : fa[x]=_find(fa[x]);}
struct LCT{
int val[mn],fa[mn],c[mn][],mx[mn],st[mn];
//mx[x]表示子树中权值最大的点的编号
bool rev[mn];
bool nroot(int x)
{
return c[fa[x]][]==x || c[fa[x]][]==x;
}
void zhuan(int x)
{
swap(c[x][],c[x][]);
rev[x]^=;
}
void pushdown(int x)
{
if(rev[x])
{
rev[x]=;
if(c[x][]) zhuan(c[x][]);
if(c[x][]) zhuan(c[x][]);
}
}
void updown(int x)
{
mx[x]=x;
if(c[x][])
{
if(val[mx[c[x][]]]>val[mx[x]])
mx[x]=mx[c[x][]];
}
if(c[x][])
{
if(val[mx[c[x][]]]>val[mx[x]])
mx[x]=mx[c[x][]];
}
}
void rotate(int x)
{
int y=fa[x],z=fa[y],flag;
if(c[y][]==x) flag=;
else flag=;
if(nroot(y))
{
if(c[z][]==y) c[z][]=x;
else c[z][]=x;
}
c[y][flag^]=c[x][flag],fa[c[x][flag]]=y;
c[x][flag]=y;
fa[y]=x,fa[x]=z;
updown(y);
updown(x);
}
void splay(int x)
{
int top=;
st[++top]=x;
for(int i=x;nroot(i);i=fa[i])
st[++top]=fa[i];
for(;top;top--) pushdown(st[top]);
while(nroot(x))
{
int y=fa[x],z=fa[y];
if(nroot(y))
{
if((c[y][]==x) ^ (c[z][]==y))
rotate(x);
else rotate(y);
}
rotate(x);
}
updown(x);
}
void access(int x)
{
int t=;
while(x){splay(x);c[x][]=t;updown(x);t=x;x=fa[x];}
}
void makeroot(int x)
{
access(x);
splay(x);
zhuan(x);
}
void link(int x,int y)
{
makeroot(x);
fa[x]=y;
}
void cut(int x,int y)
{
makeroot(x);
access(y);
splay(y);
c[y][]=fa[x]=;
updown(y);
}
int query(int x,int y)
{
makeroot(x);
access(y);
splay(y);
return mx[y];
}
}T;
void pre()
{
for(int i=;i<=n;i++)
fa[i]=i;
for(int i=;i<=m;i++)
T.val[i+n]=e[i].b;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
scanf("%d%d%d%d",&e[i].u,&e[i].v,&e[i].a,&e[i].b);
sort(e+,e++m,cmp);
ans=inf;
pre();
/* for(int i=1;i<=m;i++)
printf("%d %d\n",e[i].a,e[i].b);*/
for(int i=;i<=m;i++)
{
int x=e[i].u,y=e[i].v;
int xx=_find(x),yy=_find(y);
if(xx!=yy)
{
fa[xx]=yy;
T.link(x,i+n);
T.link(i+n,y);
}
else {
int k=T.query(x,y);
if(T.val[k]>e[i].b)
{
T.cut(e[k-n].u,k);
T.cut(k,e[k-n].v);
T.link(x,i+n);
T.link(i+n,y);
}
}
if(_find()==_find(n))
ans=min(ans,e[i].a+T.val[T.query(,n)]);
// printf("%d %d\n",e[i].a,T.query(1,n));
}
if(ans==inf) printf("-1");
else printf("%d",ans);
return ;
}
洛谷2387 BZOJ3669魔法森林题解的更多相关文章
- 洛谷 2387 NOI2014魔法森林 LCT
[题解] 我们先把边按照$a$值从小到大排序,并按照这个顺序加边. 如果当前要加入的边连接的两点$u$与$v$已经是连通的,那么直接加入这条边就会出现环.这时我们需要删除这个环中$b$值最大的边.因此 ...
- 洛谷2387 NOI2014魔法森林(LCT维护最小生成树)
本题是运用LCT来维护一个最小生成树. 是一个经典的套路 题目中求的是一个\(max(a_i)+max(b_i)\)尽可能小的路径. 那么这种的一个套路就是,先按照一维来排序,然后用LCT维护另一维 ...
- 洛谷P2387 [NOI2014]魔法森林(lct维护最小生成树)
题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2,3,…,n,边标号为 1,2,3,…, ...
- 洛谷 P2387 [NOI2014]魔法森林 解题报告
P2387 [NOI2014]魔法森林 题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2 ...
- 洛谷P2387 [NOI2014]魔法森林(LCT)
魔法森林 题目传送门 解题思路 把每条路按照\(a\)的值从小到大排序.然后用LCT按照b的值维护最小生成树,将边按照顺序放入.如果\(1\)到\(n\)有了一条路径,就更新最小答案.这个过程就相当于 ...
- 洛谷P2387 [NOI2014]魔法森林(LCT,Splay)
在XZY&XZZ巨佬的引领下,一枚蒟蒻终于啃动了这道题...... 这次还是第一次写LCT维护边权,还要化边为点,思路乱七八糟的,写起来也不顺手,还好调了许久终于AC啦. 贪心排序按一个关键字 ...
- 洛谷P2387 [NOI2014]魔法森林(LCT)
在XZY&XZZ巨佬的引领下,一枚蒟蒻终于啃动了这道题...... 这次还是第一次写LCT维护边权,还要化边为点,思路乱七八糟的,写起来也不顺手,还好调了许久终于AC啦. 贪心排序按一个关键字 ...
- 【洛谷P2387】魔法森林
题目大意:给定一个 N 个点,M 条边的无向图,边有两个边权 a, b,求从 1 号节点到 N 号节点路径的两个权值和的最大值最小是多少. 题解: 对于有两个属性的结构的最优化问题,可以考虑先按照其中 ...
- 洛谷P1783 海滩防御 分析+题解代码
洛谷P1783 海滩防御 分析+题解代码 题目描述: WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和 ...
随机推荐
- join和os.path.join 的用法
Python中有join和os.path.join()两个函数,具体作用如下: join:连接字符串数组.将字符串.元组.列表中的元素以指定的字符(分隔符)连接生成一个新的字符串os.path.joi ...
- 3.appium定位方法
1.使用id定位: driver.find_element_by_id('id的名称').click() 2.使用className定位: driver.find_element_by_class_n ...
- Leetcode138. Copy List with Random Pointer复制带随机指针的链表
给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点. 要求返回这个链表的深度拷贝. 方法一: class Solution { public: RandomLis ...
- bzoj 1050 [HAOI2006]旅行comf——kruscal
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1050 因为还有Impossible的情况,所以想到了kruscal.(?) 但好像不太行.然 ...
- How to class-dump iPad apps?
http://stackoverflow.com/questions/4776593/how-to-class-dump-ipad-apps The issue here is that the bi ...
- tesseract ocr训练 pt验证码
识别率有问题A大概率识别为n,因此需要训练,这里讲一下 如何训练 参考 java代码里边直接使用tess4j,是对tesseract的封装,但是如果要训练,还是需要在进行安装tesseract-ocr ...
- request.setCharacterEncoding("utf-8");
request.setCharacterEncoding("utf-8");不加这句话时,从input控件得到值要用new String(request.getParameter( ...
- 如何获取SpringBoot项目的applicationContext对象
ApplicationContext对象是Spring开源框架的上下文对象实例,在项目运行时自动装载Handler内的所有信息到内存.传统的获取方式有很多种,不过随着Spring版本的不断迭代,官方也 ...
- CentOS安装手册
CentOS6.5在VMware10中安装 1.启动VMware的画面 2.点击File--->New Virtual Machine 创建一台新虚拟机 3.在弹出框中选择典型安装 4.选择I ...
- java-Map-system
一 概述 0--星期日1--星期一... 有对应关系,对应关系的一方是有序的数字,可以将数字作为角标. public String getWeek(int num){ if(num<0 || n ...