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. Java—输入输出技术

    在Java中,通过java.io包提供的类来表示流,基本的输入输出流为InputStream和OutputStream.从这两个基本的输入输出流派生出面向特定处理的流,如缓冲区读写流.文件读写流等. ...

  2. Python笔记总结week2

    1. 关于Python程序执行原理:

  3. spring与mybatis三种整合方法

    spring与mybatis三种整合方法 本文主要介绍Spring与Mybatis三种常用整合方法,需要的整合架包是mybatis-spring.jar,可通过链接 http://code.googl ...

  4. RPM

    1.安装RPM 使用-ivh选项即可,能查看安装信息和进度. 例如: #RPM -ivh XXX.rpm RPM升级与更新,使用-Uvh选项或者-Fvh选项,两者略有区别. -Uvh选项:后面接的软件 ...

  5. 【Python⑤】python序列---list和tuple

    sequence 序列 sequence(序列)是一组有顺序的对象的集合.序列可以包含一个或多个元素,也可以没有任何元素. 我们之前所说的基本数据类型,都可以作为序列的对象.对象还可以是另一个序列.序 ...

  6. "$cond"

    db.items.aggregate([ { "$project": { "name": 1, "customfield": { " ...

  7. 用Runtime.getRuntime().exec()需要注意的地方

    有时候我们可能需要调用系统外部的某个程序,此时就可以用Runtime.getRuntime().exec()来调用,他会生成一个新的进程去运行调用的程序. 此方法返回一个java.lang.Proce ...

  8. Bootstrap <基础二十八>列表组

    列表组.列表组件用于以列表形式呈现复杂的和自定义的内容.创建一个基本的列表组的步骤如下: 向元素 <ul> 添加 class .list-group. 向 <li> 添加 cl ...

  9. [开发笔记]-未找到与约束ContractName Microsoft.VisualStudio.Text.ITextDocumentFactoryService...匹配的导出【转载自:酷小孩】

    原文地址:http://www.cnblogs.com/babycool/p/3199158.html 今天打算用VisualStudio2012做一个js效果页面测试的时候,打开VS2012新建项目 ...

  10. RabbitMQ Step by step(一) 安装

    RabbitMQ是一个消息中间件,可以存储转发消息,个人感觉优越于MSMQ RabbitMQ官方网站(http://www.rabbitmq.com)可以获取到安装文件,建议大家详细浏览官方网站,官方 ...