Problem 魔法森林 (NOI2014)

题目大意

  给n个点,m条边的无向图,每条边有两个权值a,b。

  求一条从1-->n的路径,使得这条路径上max(a)+max(b)最小。输出最小值即可。

解题分析

  将边按照权值a从小到大排序后,依次加边,用lct维护一棵权值b组成的最小生成树。

  具体做法是如果所加边u-->v导致形成了一个环,那么比较一下u-->v路径中的最大值和这条边的b权值大小,来决定取那条边。

  处理边权的一个做法,将每条边看成一个新的点,向其两端的点连边。

参考程序

 #include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <string>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <iostream>
#include <algorithm>
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std; #define N 200008
#define E 400008
#define LL long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define clr(x,v) memset(x,v,sizeof(x));
#define bitcnt(x) __builtin_popcount(x)
#define rep(x,y,z) for (int x=y;x<=z;x++)
#define repd(x,y,z) for (int x=y;x>=z;x--)
const int mo = ;
const int inf = 0x3f3f3f3f;
const int INF = ;
/**************************************************************************/
int n,m;
int fa[N],val[N],mx[N],rev[N],c[N][],st[N]; struct line{
int u,v,a,b;
bool operator < (const line &k) const{
return a<k.a;
}
}eg[E];
bool isroot(int k){
return c[fa[k]][]!=k && c[fa[k]][]!=k;
}
void pushup(int x){
int l=c[x][],r=c[x][];
mx[x]=x;
if (val[mx[l]]>val[mx[x]]) mx[x]=mx[l];
if (val[mx[r]]>val[mx[x]]) mx[x]=mx[r];
}
void pushdown(int x){
int l=c[x][],r=c[x][];
if (rev[x]){
if (l) rev[l]^=;
if (r) rev[r]^=;
rev[x]^=;
swap(c[x][],c[x][]);
}
}
void rotate(int x){
int y=fa[x],z=fa[y],l,r;
if (c[y][]==x) l=; else l=; r=l^;
if (!isroot(y)){
if (c[z][]==y) c[z][]=x; else c[z][]=x;
}
fa[x]=z; fa[y]=x; fa[c[x][r]]=y;
c[y][l]=c[x][r]; c[x][r]=y;
pushup(y); pushup(x);
}
void splay(int x){
int top=; st[++top]=x;
for (int i=x;!isroot(i);i=fa[i]) st[++top]=fa[i];
while (top) pushdown(st[top--]);
while (!isroot(x)){
int y=fa[x],z=fa[y];
if (!isroot(y)){
if (c[y][]==x^c[z][]==y) rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x){
int t=;
while (x){
splay(x);
c[x][]=t;
pushup(x);
t=x; x=fa[x];
}
}
void rever(int x){
access(x); splay(x); rev[x]^=;
}
void link(int u,int v){
rever(u); fa[u]=v;
}
void cut(int u,int v){
rever(u); access(v); splay(v); fa[c[v][]]=; c[v][]=; pushup(v);
}
int find(int u){
access(u); splay(u);
while (c[u][]) u=c[u][];
return u;
}
int query(int u,int v){
rever(u); access(v); splay(v); return mx[v];
} int main(){
scanf("%d%d",&n,&m);
rep(i,,m) scanf("%d%d%d%d",&eg[i].u,&eg[i].v,&eg[i].a,&eg[i].b);
sort(eg+,eg+m+);
int ans=INF;
rep(i,,m){
int u=eg[i].u,v=eg[i].v,a=eg[i].a,b=eg[i].b;
int flag=;
if (find(u)==find(v)){
int t=query(u,v);
if (b<val[t]){
cut(t,eg[t-n].u);
cut(t,eg[t-n].v);
}
else flag=;
}
if (flag) {
val[i+n]=b; mx[n+i]=n+i;
link(i+n,u);
link(i+n,v);
}
if (find()==find(n)){
int t=query(,n);
ans=min(ans,val[t]+a);
}
}
printf("%d\n",ans==INF?-:ans);
}

BZOJ3669 (动态树)的更多相关文章

  1. 动态树(Link-Cut-Tree)简单总结(指针版本)

    Link-Cut-Tree(动态树 LCT) 1.定义 1. 偏爱子节点: 一颗子树内最后访问的点若在该子树根节点 X 的某个儿子节点 P 的子树中,则称 P 为 X 的偏爱子节点. 偏爱边:连向偏爱 ...

  2. 如何利用FineReport制作动态树报表

    在对数据字段进行分类管理时,利用动态树折叠数据是一个很好的方法,也就是点击数据前面的加号才展开对应下面的数据,如下图.那这样的效果在制作报表时该如何实现呢? 下面以报表工具FineReport为例介绍 ...

  3. 动态树之LCT(link-cut tree)讲解

    动态树是一类要求维护森林的连通性的题的总称,这类问题要求维护某个点到根的某些数据,支持树的切分,合并,以及对子树的某些操作.其中解决这一问题的某些简化版(不包括对子树的操作)的基础数据结构就是LCT( ...

  4. 【BZOJ-3589】动态树 树链剖分 + 线段树 + 线段覆盖(特殊的技巧)

    3589: 动态树 Time Limit: 30 Sec  Memory Limit: 1024 MBSubmit: 405  Solved: 137[Submit][Status][Discuss] ...

  5. BZOJ-2049 Cave洞穴勘测 动态树Link-Cut-Tree (并查集骗分TAT)

    2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec Memory Limit: 259 MB Submit: 5833 Solved: 2666 [Submit] ...

  6. 学习笔记-动态树Link-Cut-Tree

    --少年你有梦想吗? --少年你听说过安利吗? 安利一个集训队讲解:http://wenku.baidu.com/view/75906f160b4e767f5acfcedb 关于动态树问题,有多种方法 ...

  7. BZOJ 3589 动态树(子树操作,链查询)

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3589 题意:给出一棵有根树,两种操作:(1)以u为根的子树所有节点权值加上一个数字 ...

  8. Tsinsen A1517. 动态树 树链剖分,线段树,子树操作

    题目 : http://www.tsinsen.com/A1517 A1517. 动态树 时间限制:3.0s   内存限制:1.0GB    总提交次数:227   AC次数:67   平均分:49. ...

  9. 动态树 Link-Cut Trees

    动态树 动态树问题, 即要求我们维护一个由若干棵子结点无序的有根树组成的森林. 要求这个数据结构支持对树的分割.合并,对某个点到它的根的路径的某些操作,以及对某个点的子树进行的某些操作. 在这里我们考 ...

  10. bzoj 2594: [Wc2006]水管局长数据加强版 动态树

    2594: [Wc2006]水管局长数据加强版 Time Limit: 25 Sec  Memory Limit: 128 MBSubmit: 934  Solved: 291[Submit][Sta ...

随机推荐

  1. JS学习笔记01

    文章转载pigpigpig4587 的 1.Javascript是区分大小写的语言.也就是说.关键字.变量,函数和所有的标识符都必须采取一致的大小写形式.因为html不严格区分大小写,所以在html中 ...

  2. CSS3 仿微信聊天小气泡

    今天给大家分享一个我刚做的项目中的一个小案例, 因为我们在做一个聊天的功能,之前的聊天页面UI很丑,我就不在这里展示给大家了. 现在就教大家怎么用css3制作一个和微信聊天界面一样的页面. 首先给大家 ...

  3. (转)Tomcat数据源连接池加密

    文章来源 :http://my.oschina.net/cimu/blog/164757 我们在使用Tomcat数据库连接池的时候都是明文存储数据库用户名和密码的,例如: <Resource n ...

  4. Anjs分词器以及关键词抓取使用的方法

    首先介绍一下这个网址非常有用本文所有的关于Anjs起源来自这里请先查看一下 https://github.com/NLPchina/ansj_seg 在本次测试使用的是     import java ...

  5. Bitmap 的几种压缩方式

    微信的缩略图要求是不大于32k,这就需要对我的图片进行压缩.试了几种方法,一一道来. 代码如下 ByteArrayOutputStream baos =  new  ByteArrayOutputSt ...

  6. Fragment的startActivityForResult和Activity的startActivityForResult的区别

    2016-08-30 18:22:33 前提:我们的APP要兼容Api level 11以前的,所以必须用FragmentActivity 1.对于Fragment的,我们很多时候都会在Activit ...

  7. 简易线程池Thread Pool

    1. 基本思路 写了个简易的线程池,基本的思路是: 有1个调度线程,负责维护WorkItem队列.管理线程(是否要增加工作线程).调度(把工作项赋给工作线程)等 线程数量随WorkItem的量动态调整 ...

  8. 非maven项目导入idea几点心得总结

    这个问题一共有3种解决办法1. 你下载好的文件应该是src 和Webcontent是在同一个目录下的.只要把Webcontent放入到src下就行.这种就变成maven的目录结构.因为你这个目录结构应 ...

  9. JAVA 中文转GBK内码方法

    不能谷歌,百度了很久,没有直接的转换方法,参考 byte[]数组与十六进制字符串与字符串的互相转换 http://blog.163.com/roadwalker@126/blog/static/113 ...

  10. JAVA多线程超时加载当网页图片

    先上图: 这一次没有采取正则匹配,而采取了最简单的java分割和替代方法进行筛选图片 它能够筛选如下的图片并保存到指定的文件夹 如: “http://xxxx/xxxx/xxx.jpg” 'http: ...