【BZOJ3669】[Noi2014]魔法森林 LCT
终于不是裸的LCT了。。。然而一开始一眼看上去这是kruskal。。不对,题目要求1->n的路径上的每个点的两个最大权值和最小,这样便可以用LCT来维护一个最小生成路(瞎编的。。。),先以a为关键字排序,然后加边,所以每次加入一条边时a一定是最大的,考虑b的大小,当形成环时,考虑用当前边替换掉环内b最大的边,当然是当前边b小于权值最大的边拉!
Tips:1.注意LCT要把每条边也作为一个节点,方便连接,然后每个节点维护所在边在边集里的编号即可。
#include <iostream>
#include <cstdio>
#include <algorithm>
#define N 50050
#define M 100100
#define inf 0x7fffffff
using namespace std;
int n,m,ans;
struct E{int x,y,a,b;}e[M];
struct node
{
node *fa,*ch[];
void init();
int pos,rpos;
bool rev;
bool chr() {return this==fa->ch[];}
bool isrt() {return this!=fa->ch[] && this!=fa->ch[];}
void setc(node *x,int t) {this->ch[t]=x; x->fa=this;}
void push_up();
void push_down();
/* void push_down()
{
if (this==null) return;
if (!x->isrt()) x->fa->push_down();
if (rev)
{
ch[1]->rev^=1;
ch[0]->rev^=1;
swap(ch[1],ch[0]);
rev=0;
}
}
void push_up()
{
if (this==null) return;
pos=rpos;
if (ch[0]!=null && e[pos].b<e[ch[0]->pos].b) pos=ch[0]->pos;
if (ch[1]!=null && e[pos].b<e[ch[1]->pos].b) pos=ch[1]->pos;
}*/
}pool[N+M],*pt=pool,*point[N],*et[M],*null;
void node::init() {ch[]=ch[]=fa=null; pos=; rev=; rpos=;}
void node::push_up()
{
if (this==null) return;
pos=rpos;
if (ch[]!=null && e[pos].b<e[ch[]->pos].b) pos=ch[]->pos;
if (ch[]!=null && e[pos].b<e[ch[]->pos].b) pos=ch[]->pos;
}
void node::push_down()
{
if (this==null) return;
if (!this->isrt()) this->fa->push_down();
if (rev)
{
if (ch[]!=null) ch[]->rev^=;
if (ch[]!=null) ch[]->rev^=;
swap(ch[],ch[]);
rev=;
}
}
namespace LCT
{
node *NewNode()
{
pt++;
pt->init();
return pt;
}
void rotate(node *x)
{
node *r=x->fa;
if (x==null || r==null) return;
int t=x->chr();
if (r->isrt()) x->fa=r->fa;
else r->fa->setc(x,r->chr());
r->setc(x->ch[t^],t);
x->setc(r,!t);
x->push_up(); r->push_up();
}
void Splay(node *x)
{
x->push_down();
for (;!x->isrt();rotate(x))
if (!x->fa->isrt())
if (x->chr()==x->fa->chr()) rotate(x->fa);
else rotate(x);
x->push_up();
}
void Access(node *x)
{
node *r=null;
for (;x!=null;r=x,x=x->fa)
{
Splay(x);
x->ch[]=r;
}
}
void MoveRoot(node *x)
{
Access(x);
Splay(x);
x->rev^=;
}
void Link(node *x,node *y)
{
MoveRoot(x);
x->fa=y;
}
void Cut(node *x,node *y)
{
MoveRoot(x);
Access(y); Splay(y);
y->ch[]->fa=null; y->ch[]=null;
}
node *Find(node *x)
{
Access(x);
Splay(x);
while (x->ch[]!=null) x=x->ch[];
return x;
}
int Query(node *x,node *y)
{
MoveRoot(x);
Access(y);Splay(y);
return y->pos;
}
}
inline int read()
{
char c;
int ans=,f=;
while (!isdigit(c=getchar())) if (c=='-') f=-;
ans=c-'';
while (isdigit(c=getchar())) ans=ans*+c-'';
return ans*f;
}
inline bool cmp (E a,E b) {return a.a<b.a;}
using namespace LCT;
int main()
{
n=read();m=read();
null=pt++;
null->init();
for (int i=;i<=m;i++) {e[i].x=read(); e[i].y=read(); e[i].a=read(); e[i].b=read();}
for (int i=;i<=n;i++) point[i]=NewNode();
sort(e+,e+m+,cmp);
ans=inf;e[].b=-inf;
for (int i=;i<=m;i++)
{
int x=e[i].x,y=e[i].y,b=e[i].b;
et[i]=NewNode(); et[i]->pos=et[i]->rpos=i;
if (Find(point[x])==Find(point[y]))
{
int pos=Query(point[x],point[y]);
if (e[pos].b>b)
{
Cut(et[pos],point[e[pos].x]);
Cut(et[pos],point[e[pos].y]);
Link(et[i],point[x]);
Link(et[i],point[y]);
}
}
else
{
Link(et[i],point[x]);
Link(et[i],point[y]);
}
if (Find(point[])==Find(point[n])) ans=min(ans,e[i].a+e[Query(point[],point[n])].b);
}
if (ans!=inf) printf("%d\n",ans);
else printf("-1\n");
return ;
}
Description
为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士。魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M。初始时小E同学在号节点1,隐士则住在号节点N。小E需要通过这一片魔法森林,才能够拜访到隐士。
魔法森林中居住了一些妖怪。每当有人经过一条边的时候,这条边上的妖怪就会对其发起攻击。幸运的是,在号节点住着两种守护精灵:A型守护精灵与B型守护精灵。小E可以借助它们的力量,达到自己的目的。
只要小E带上足够多的守护精灵,妖怪们就不会发起攻击了。具体来说,无向图中的每一条边Ei包含两个权值Ai与Bi。若身上携带的A型守护精灵个数不少于Ai,且B型守护精灵个数不少于Bi,这条边上的妖怪就不会对通过这条边的人发起攻击。当且仅当通过这片魔法森林的过程中没有任意一条边的妖怪向小E发起攻击,他才能成功找到隐士。
由于携带守护精灵是一件非常麻烦的事,小E想要知道,要能够成功拜访到隐士,最少需要携带守护精灵的总个数。守护精灵的总个数为A型守护精灵的个数与B型守护精灵的个数之和。
Input
第1行包含两个整数N,M,表示无向图共有N个节点,M条边。 接下来M行,第行包含4个正整数Xi,Yi,Ai,Bi,描述第i条无向边。其中Xi与Yi为该边两个端点的标号,Ai与Bi的含义如题所述。 注意数据中可能包含重边与自环。
Output
输出一行一个整数:如果小E可以成功拜访到隐士,输出小E最少需要携带的守护精灵的总个数;如果无论如何小E都无法拜访到隐士,输出“-1”(不含引号)。
Sample Input
4 5
1 2 19 1
2 3 8 12
2 4 12 15
1 3 17 8
3 4 1 17
【输入样例2】
3 1
1 2 1 1
Sample Output
32
【样例说明1】
如果小E走路径1→2→4,需要携带19+15=34个守护精灵;
如果小E走路径1→3→4,需要携带17+17=34个守护精灵;
如果小E走路径1→2→3→4,需要携带19+17=36个守护精灵;
如果小E走路径1→3→2→4,需要携带17+15=32个守护精灵。
综上所述,小E最少需要携带32个守护精灵。
【输出样例2】
-1
【样例说明2】
小E无法从1号节点到达3号节点,故输出-1。
HINT
2<=n<=50,000
0<=m<=100,000
1<=ai ,bi<=50,000
Source
【BZOJ3669】[Noi2014]魔法森林 LCT的更多相关文章
- bzoj3669: [Noi2014]魔法森林 lct版
先上题目 bzoj3669: [Noi2014]魔法森林 这道题首先每一条边都有一个a,b 我们按a从小到大排序 每次将一条路劲入队 当然这道题权在边上 所以我们将边化为点去连接他的两个端点 当然某两 ...
- bzoj3669: [Noi2014]魔法森林 lct
记得去年模拟赛的时候好像YY出二分答案枚举a,b的暴力,过了55欸 然后看正解,为了将两维变成一维,将a排序,模拟Kruskal的加边过程,同时维护1到n的最大值,加入一条边e(u,v,a,b)时有以 ...
- [bzoj3669][Noi2014]魔法森林——lct
Brief description 给定一个无向图,求从1到n的一条路径使得这条路径上最大的a和b最小. Algorithm Design 以下内容选自某HN神犇的blog 双瓶颈的最小生成树的感觉, ...
- 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 ...
- [NOI2014]魔法森林 LCT
题面 [NOI2014]魔法森林 题解 一条路径的代价为路径上的\(max(a[i]) + max(b[i])\),因为一条边同时有$a[i], b[i]$2种权值,直接处理不好同时兼顾到,所以我们考 ...
- loj2245 [NOI2014]魔法森林 LCT
[NOI2014]魔法森林 链接 loj 思路 a排序,b做动态最小生成树. 把边拆成点就可以了. uoj98.也许lct复杂度写假了..越卡常,越慢 代码 #include <bits/std ...
- BZOJ3669[Noi2014]魔法森林——kruskal+LCT
题目描述 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M.初始时小E同学在号节点1,隐士则住 ...
- BZOJ3669: [Noi2014]魔法森林(瓶颈生成树 LCT)
Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 3558 Solved: 2283[Submit][Status][Discuss] Descript ...
随机推荐
- Windows XP系统下添加任务计划常出现问题解决办法
Windows XP系统下添加任务计划常出现问题解决办法 计划任务就是让电脑在指定的时间内执行指定的动作(计划动作),这些动作可以是一个程序,也可以是一个批处理,但是至少是可以运行的(通俗一些就是双击 ...
- Mysql导入数据命令
转自:http://blog.sina.com.cn/s/blog_610997850100mwv8.html 今天碰到个问题要用phpmyadmin导入1G的数据,但是在怎么都导入不了,用命令行就可 ...
- Unity里的Mesh属性
----------------------------------------------------------------------------------------------- Mesh ...
- 微信公众平台可通过UnionID机制在多公众号间帐号互通
微信公众平台越来越注重开发者的反馈信息了,这不,微信开放平台提供了UnionID机制,通过获取用户基本信息接口,开发者可通过OpenID来获取用户基本信息,而如果开发者拥有多个公众号,可使用以下办法通 ...
- sdcms标签
模板防盗:<%if not in_sdcms then response.write("template load fail"):response.end() end if% ...
- git 教程(15)--分支管理策略
通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息. 如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的comm ...
- CF100965C题解..
求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...
- python——连接Oracle数据库
前言 Python自带的模块中有很多操纵文件的.我们可以把文件的数据读出来,经过处理还可以将数据写入文件中.但是对于数据的管理和分析来说,数据库还是专业一些.如果Python能和数据库结合在一起,那么 ...
- resin 安装配置
resin (下载免费版 4) 前提:已经安装了Java运行环境,resin的安装需要jdk的支持 一.安装 1.cd /usr/local/src wget http://www.caucho. ...
- node03-events
目录:node01-创建服务器 node02-util node03-events node04-buffer node05-fs node06-path node07-http node08-exp ...