这道题呢,

首先按照关键字a排序,然后不断地加边,用lct维护这个过程

具体实现: 先按照关键字a排序,枚举每一条边,判断两点是否已经联通(kruskal 部分)如果联通,就在两点路径间寻找最大的b, 和这条边的b值相比较,如果更大一些,就切断u,v之间的路径, 并连上这条边;

如果不联通,就让它联通(好随意啊= =

最后寻找路径之间最大的b + 当前的a,和原来的答案相比较。

剩下的用lct维护

注意联通的方式是把把边看做点, 然后连接(所以加上n)   ->link(u, i + n);  link(v, i + n);

(由于我一直不理解怎么保证当前的a一定在路径上,所以这是自己yy的证明(可能有很大的bug,勿喷):当前的a如果不在(1,n)路径之中,但(1,n)已联通,那么最优值在之前已经被计算过,否则由于a是递增的,那么此时的a就是路径中最大的a)

下面是代码

 /**************************************************************
    Problem: 3669
    User: cminus
    Language: C++
    Result: Accepted
    Time:5104 ms
    Memory:6128 kb
****************************************************************/
 
#include <cstdio>
#include <algorithm>
using namespace std;
#define l(x) ch[x][0]
#define r(x) ch[x][1]
#define kd(x) (r(fa[x]) == x)
#define setc(f, c, k)   (ch[fa[c] = f][k] = c)
#define isRoot(x)   (r(fa[x]) != x && l(fa[x]) != x)
const int N = ;
 
struct Edge{
    int u, v, a, b;
    inline void init(){
        scanf("%d %d %d %d", &u, &v, &a, &b);
    }
    inline bool operator <(const Edge &rhs)const{
        return a < rhs.a;
    }
}e[];
int fa[N], ch[N][], rev[N], val[N], maxp[N], f[];
int INF = 0x7f7f7f7f;
 
inline void update(int x) {
    maxp[x] = x;
    if (val[maxp[x]] < val[maxp[l(x)]])  maxp[x] = maxp[l(x)];
    if (val[maxp[x]] < val[maxp[r(x)]])  maxp[x] = maxp[r(x)];
}
 
inline void push(int x) {
    if (rev[x] and x){
        rev[x] = ;
        if (l(x))   rev[l(x)] ^= , swap(l(l(x)), r(l(x)));
        if (r(x))   rev[r(x)] ^= , swap(l(r(x)), r(r(x)));
    }
}
 
inline void pushDown(int x) {
    if (! isRoot(x))    pushDown(fa[x]);
    push(x);
}
 
inline void rotate(int x) {
    int y = fa[x], t = kd(x);
    setc(y, ch[x][t^], t);
    if (isRoot(y)) fa[x] = fa[y];
    else setc(fa[y], x, kd(y));
    setc(x, y, t^);
    update(y); update(x);
}
 
inline void splay(int x){
    pushDown(x);
    while(! isRoot(x)){
        if (! isRoot(fa[x]))
            if (kd(x) == kd(fa[x]))     rotate(fa[x]);
            else    rotate(x); rotate(x);
    }
}
 
inline void access(int x){
    int t = ;
    while(x) {
        splay(x);
        r(x) = t; update(x);
        t = x; x = fa[x];
    }
}
 
inline void makeRoot(int x){
    access(x); splay(x);
    rev[x] ^= ;  swap(l(x), r(x));
}
 
inline void link(int u, int v) {    makeRoot(u);  fa[u] = v; }
 
inline void cut(int u, int v){
    makeRoot(u);
    access(v); splay(v);
    fa[u] = l(v) = ;
}
 
inline int query(int u, int v){
    makeRoot(u);
    access(v); splay(v);
    return maxp[v];
}
 
int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }
 
int main(){
    int n, m;
    scanf("%d %d", &n, &m);
    int ans = INF;
    for (int i = ; i <= m; i++) e[i].init();
    for (int i = ; i <= n; i++) f[i] = i;
    sort(e + , e + m + );
    for (int i = ; i <= m; i++){
        int u = e[i].u, v = e[i].v, rt1 = find(u), rt2 = find(v);
        val[i + n] = e[i].b; maxp[i + n] = i + n;
        if (rt1 == rt2){
            int p = query(u, v);
            if (val[p] > e[i].b)   cut(u, p), cut(v, p);
            else   continue;   
        }
        else f[rt1] = rt2;
        link(u, i + n); link(v, i + n);
        if (find() == find(n)) ans = min(ans, val[query(, n)] + e[i].a);
    }
    printf("%d\n", ans == INF ? - : ans);
    return ;
}

bzoj 3669: [Noi2014]魔法森林 (LCT & kruskal)的更多相关文章

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

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

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

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

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

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

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

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

  5. BZOJ 3669: [Noi2014]魔法森林(lct+最小生成树)

    传送门 解题思路 \(lct\)维护最小生成树.我们首先按照\(a\)排序,然后每次加入一条边,在图中维护一棵最小生成树.用并查集判断一下\(1\)与\(n\)是否联通,如果联通的话就尝试更新答案. ...

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. WSL的ssh-agent问题

    WSL , 使用forwardAgent 的时候 , 用的以下两个应用 ubuntu 18.04 . ubuntu 这两个应用的 ssh-agent是有问题的 . 详见 https://github. ...

  2. 错误 CS8107 C# 7.0 中不支持功能“xxxxxx”。请使用 7.1 或更高的语言版本。

    解决方法:项目右键属性 —> 生成 —> 找到最下面的高级按钮,点击高级按钮 —> 常规 —> 语言版本 —> 选择 C#最新次要版本,或者比当前版本更高的版本即可,点击 ...

  3. Qt Gui 第六章布局管理

    1.QRadioButton之间如何互斥 其中一种方法是将各个QRadioButton控件放在同一个toolbarsLayout或者toolbarsGroupBox即可:如下所示 toolbarsGr ...

  4. Wannafly Camp 2020 Day 1D 生成树 - 矩阵树定理,高斯消元

    给出两幅 \(n(\leq 400)\) 个点的无向图 \(G_1 ,G_2\),对于 \(G_1\) 的每一颗生成树,它的权值定义为有多少条边在 \(G_2\) 中出现.求 \(G_1\) 所有生成 ...

  5. AI 所需的数学基础

    一.[微积分] 基础概念(极限.可微与可导.全导数与偏导数):只要学微积分,就必须要明白的概念,否则后面什么都无法继续学习. 函数求导:求导是梯度的基础,而梯度是 AI 算法的基础,因此求导非常重要! ...

  6. Selenium3+python自动化014-自动化测试框架的作用

    1.能够有效组织和管理测试脚本 2.进行数据驱动或者关键字驱动的测试 3.将基础的测试代码进行封装,降低测试脚本编写的复杂性和重复性 4.提高测试脚本维护和修改的效率 5.自动执行测试脚本,并自动发布 ...

  7. java学习笔记之IO编程—打印流和BufferedReader

    1.打印流(PrintWriter) 想要通过程序实现内容输出,其核心一定是要依靠OutputStream类,但是OutputStream类有一个最大缺点,就是这个类中的输出操作功能有限,所有的数据一 ...

  8. SpringBoot整合WEB开发--(十)配置AOP

    简介: SpringBoot框架中对AOP有很好的支持,简单AOP概念: JoinPoint(连接点):类里面可以被增强的方法即为连接点,例如,想修改哪个方法的功能,那么该方法就是一个连接点. Poi ...

  9. 群晖DSM修改ssh权限实现免密码登陆

    问题 使用ssh-id-copy正确上传公钥后依然无法免密码登陆 原因 群晖DSM中.ssh文件夹权限不当 解决 赋予正确权限 admin@DiskStation:/var/services/home ...

  10. 获取redis实例中最大的top-N key

    需求:获取redis实例中最大的top-N key 说明:由于redis 4.x才引入了memory usage keyname的语法.3.x不支持! db_ip=5.5.5.101 db_port= ...