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. vb.net 网络图片

    https://msdn.microsoft.com/zh-cn/library/ms251715(VS.80).aspx

  2. split 分割 字符串(分隔符如:* ^ : | , .) 及注意点

    http://blog.sina.com.cn/s/blog_b6487d470101g0hp.html [1]单个符号作为分隔符         String address="上海|上海 ...

  3. STC12C5A60S2 双串口通信

    STC12C5A60S2单片机是一款功能比较强大的单片机,它拥有两个全双工串行通信接口,串口1的功能及操作与传统51单片机串行口相同:特殊的是STC12C5A60S2单片机内部有一个独立波特率发生器, ...

  4. Adb refused a command 解决方法

    原文:How To Fix Android Error Adb Refused A Command 地址:http://downloadfixit.com/android-error-adb-refu ...

  5. Xcode5 + phoneGap2.9搭建ios开发环境-配置-测试-归档上传/phoneG...

    前言: 小弟是做JAVA/Android的第一次搞这个ios,公司有mobile项目是使用phoneGap开发的,需要开发ios版本.什么都不会只能一点一点琢磨了……大神越过…… 原文链接:http: ...

  6. E. Vasya and Beautiful Arrays

    http://codeforces.com/contest/355/problem/E 每个数都可以变成段 [a-k,a], 某一个因子是否被所有的段包含,就是把这个因子以及它的所有倍数看成点, 看是 ...

  7. nginx 模块讲解

    1. 通用配置选项: --prefix=<path>          指定Nginx的安装路径,所有其他的路径都要依赖于该选项 --sbin-path=<path>     ...

  8. JS中的数据类型检测

    JavaScript的数据类型分为两类:原始类型(primitive type)和对象类型(object type).原始类型有5种,分别是:数字(Number).字符串(String).布尔值(Bo ...

  9. iOS权限问题

    判断相机权限: NSString *mediaType = AVMediaTypeVideo; AVAuthorizationStatus authStatus = [AVCaptureDevice ...

  10. 资源:Python for Windows

    http://win32com.goermezer.de/content/blogsection/7/284/ 一个网站,有各种Windows 下使用 Python 的脚本示例,很不错,有待继续挖掘. ...