【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=3669

【题目大意】

  给出一张图,每条边上有两个值ai和bi,现在需要求出一条1到N的路,
  求使得路上ai的最大值与bi的最大值的和最小。

【题解】

  我们按照ai的权值从小到大排序,依次加边,我们只要求出bi最大值最小的生成路即可,
  我们加入边的时候如果发现之前两个点是相连的,并且路径中bi最大值比当前加入的边要大,
  那么我们把原来大的那条边cut掉,加入现在这条边。
  动态树对于边的处理可以将边权转化为点权。

【代码】

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=200010,INF=0x3f3f3f3f;
int f[N],son[N][2],val[N],mx[N],tmp[N],from[N];bool rev[N];
bool isroot(int x){return !f[x]||son[f[x]][0]!=x&&son[f[x]][1]!=x;}
void rev1(int x){if(!x)return;swap(son[x][0],son[x][1]);rev[x]^=1;}
void pb(int x){if(rev[x])rev1(son[x][0]),rev1(son[x][1]),rev[x]=0;}
void up(int x){
mx[x]=val[x],from[x]=x;
if(son[x][0])if(mx[son[x][0]]>mx[x])mx[x]=mx[son[x][0]],from[x]=from[son[x][0]];
if(son[x][1])if(mx[son[x][1]]>mx[x])mx[x]=mx[son[x][1]],from[x]=from[son[x][1]];
}
void rotate(int x){
int y=f[x],w=son[y][1]==x;
son[y][w]=son[x][w^1];
if(son[x][w^1])f[son[x][w^1]]=y;
if(f[y]){
int z=f[y];
if(son[z][0]==y)son[z][0]=x;else if(son[z][1]==y)son[z][1]=x;
}f[x]=f[y];f[y]=x;son[x][w^1]=y;up(y);
}
void splay(int x){
int s=1,i=x,y;tmp[1]=i;
while(!isroot(i))tmp[++s]=i=f[i];
while(s)pb(tmp[s--]);
while(!isroot(x)){
y=f[x];
if(!isroot(y)){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);}
rotate(x);
}up(x);
}
void access(int x){for(int y=0;x;y=x,x=f[x])splay(x),son[x][1]=y,up(x);}
int root(int x){access(x);splay(x);while(son[x][0])x=son[x][0];return x;}
void makeroot(int x){access(x);splay(x);rev1(x);}
void link(int x,int y){makeroot(x);f[x]=y;access(x);}
void cutf(int x){access(x);splay(x);f[son[x][0]]=0;son[x][0]=0;up(x);}
void cut(int x,int y){makeroot(x);cutf(y);}
int ask(int x,int y){makeroot(x);access(y);splay(y);return mx[y];}
int askfrom(int x,int y){makeroot(x);access(y);splay(y);return from[y];}
void init(){
memset(son,0,sizeof(son));
memset(rev,0,sizeof(rev));
memset(f,0,sizeof(f));
memset(val,0,sizeof(val));
}
struct edge{int x,y,a,b;}e[N];
bool cmp(edge a,edge b){return a.a<b.a;}
int n,m;
int main(){
while(~scanf("%d%d",&n,&m)){
init();
int ans=INF;
for(int i=1;i<=m;i++)scanf("%d%d%d%d",&e[i].x,&e[i].y,&e[i].a,&e[i].b);
sort(e+1,e+m+1,cmp);
for(int i=1;i<=m;i++)val[n+i]=e[i].b,from[n+i]=n+i;
for(int i=1;i<=m;i++){
if(root(e[i].x)!=root(e[i].y))link(e[i].x,n+i),link(e[i].y,n+i);
else{
int pos=askfrom(e[i].x,e[i].y);
if(e[i].b<val[pos]){
cut(pos,e[pos-n].x),cut(pos,e[pos-n].y);
link(e[i].x,n+i),link(e[i].y,n+i);
}
}if(root(1)==root(n))ans=min(ans,e[i].a+ask(1,n));
}if(ans==INF)puts("-1");
else printf("%d\n",ans);
}return 0;
}

BZOJ 3669 [Noi2014]魔法森林(贪心+LCT)的更多相关文章

  1. [BZOJ 3669] [Noi2014] 魔法森林 【LCT】

    题目链接:BZOJ - 3669 题目分析 如果确定了带 x 只精灵A,那么我们就是要找一条 1 到 n 的路径,满足只经过 Ai <= x 的边,而且要使经过的边中最大的 Bi 尽量小. 其实 ...

  2. bzoj 3669: [Noi2014]魔法森林

    bzoj 3669: [Noi2014]魔法森林 Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号 ...

  3. BZOJ 3669: [Noi2014]魔法森林( LCT )

    排序搞掉一维, 然后就用LCT维护加边MST. O(NlogN) ------------------------------------------------------------------- ...

  4. bzoj 3669: [Noi2014]魔法森林 (LCT)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3669 题面: 3669: [Noi2014]魔法森林 Time Limit: 30 Sec  ...

  5. bzoj 3669: [Noi2014]魔法森林 动态树

    3669: [Noi2014]魔法森林 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 363  Solved: 202[Submit][Status] ...

  6. bzoj 3669: [Noi2014]魔法森林 -- 动点spfa

    3669: [Noi2014]魔法森林 Time Limit: 30 Sec  Memory Limit: 512 MB 动点spfa Description 为了得到书法大家的真传,小E同学下定决心 ...

  7. 【BZOJ】3669: [Noi2014]魔法森林(lct+特殊的技巧)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3669 首先看到题目应该可以得到我们要最小化 min{ max{a(u, v)} + max{b(u, ...

  8. bzoj 3669: [Noi2014] 魔法森林 LCT版

    Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M.初始时小E同学在号节 ...

  9. BZOJ 3669: [Noi2014]魔法森林 [LCT Kruskal | SPFA]

    题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2,3,…,n,边标号为 1,2,3,…, ...

  10. bzoj 3669: [Noi2014]魔法森林(并查集+LCT)

    Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M.初始时小E同学在号节 ...

随机推荐

  1. 【洛谷 P4008】 [NOI2003]文本编辑器 (Splay)

    题目链接 \(Splay\)先练到这吧(好像还有道毒瘤的维护数列诶,算了吧) 记录下光标的编号,维护就是\(Splay\)基操了. 另外数据有坑,数据是\(Windows\)下生成了,回车是'\n\r ...

  2. HDU 2546 饭卡 (dp)

    题目链接 Problem Description 电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额.如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上 ...

  3. 将资源文件夹中的文件通过流的方式写入到应用的File文件夹中

    //1.在Files文件夹中创建同名的数据库文件 File files = getFilesDir(); File file = new File(files, DBName); if(file.ex ...

  4. Part2-HttpClient官方教程-Chapter6-HTTP缓存(HTTP Caching)

    原文链接 6.1. 一般概念 HttpClient Cache提供了一个与HTTP / 1.1兼容的缓存层与HttpClient(浏览器缓存的Java等价物.)一起使用.该实现遵循责任链设计模式,其中 ...

  5. 第一章:read/sysread/print/syswrite区别

    use strict; use warnings; #将读入的内容添加到原字符串后面 my $buffer='START:'; , length($buffer)); #my $byts = read ...

  6. 仿照linux dpm机制,实现自己的dpm【转】

    转自:http://blog.csdn.net/lixiaojie1012/article/details/23788713 前边我们讨论分析了linux 内核的dpm实现,分析的目的在于学以致用:在 ...

  7. swiper 滑动插件,小屏单个显示滑动,大屏全部显示

    var currSwiperIndex=0; function widthHandle(){ var level = widthLevel(); if(level==1){ //单个显示,滑动 if( ...

  8. 使用js获取url里的指定参数

    String.prototype.getQuery = function(name){     var reg = new RegExp("(^|&)"+ name +&q ...

  9. Go语言基础单元测试示例

    这个要熟悉原理,要能写.. 但现在..... 注意,没有main函数,以_test.go结尾,命令go test -v package main import ( "testing" ...

  10. 关于星号(**/*.java)

    关于星号(**/*.java) (1)前面两个星号(**)表示在项目的所有文件夹(包括子文件夹)中的文件:*.java表示以 .java结尾的所有文件. (2)如果前面两个星号(**)没有,只有星号( ...