zoukankan      html  css  js  c++  java
  • [P2387魔法森林

    题面

    题意:

    给出一个图,边权有两维,ab. 求1n的一条路径使得路径经过的边的最大的ab的和最小,输出最小之和。

    (Solution:)

    如果做过这题,那么就显得很简单了很好想了。

    又是想让路径上最大的边权尽可能小,于是就想到先对 b 从小到大 Kruscal 加边,然后维护链上 a 的最大边,如果当前 link(u,v) 成环了,假设之前 uv 路径上最大边是 x->y , 如果 x->y.a > u->v.acut(x,y),link(u,v).

    (Source)

    #include <set>
    #include <cmath>
    #include <cctype>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <assert.h>
    #include <algorithm>
    
    using namespace std;
    
    #define fir first
    #define sec second
    #define pb push_back
    #define mp make_pair
    #define LL long long
    #define INF (0x3f3f3f3f)
    #define mem(a, b) memset(a, b, sizeof (a))
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    #define ____ debug("go")
    #define Debug(x) cout << #x << " = " << x << endl
    #define tralve(i, x) for (register int i = head[x]; i; i = nxt[i])
    #define For(i, a, b) for (register int (i) = (a); (i) <= (b); ++ (i))
    #define Forr(i, a, b) for (register int (i) = (a); (i) >= (b); -- (i))
    #define file(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
    
    namespace io {
        static char buf[1<<21], *pos = buf, *end = buf;
        inline char getc()
        { return pos == end && (end = (pos = buf) + fread(buf, 1, 1<<21, stdin), pos == end) ? EOF : *pos ++; }
        inline int rint() {
            register int x = 0, f = 1;register char c;
            while (!isdigit(c = getc())) if (c == '-') f = -1;
            while (x = (x << 1) + (x << 3) + (c ^ 48), isdigit(c = getc()));
            return x * f;
        }
        inline LL rLL() {
            register LL x = 0, f = 1; register char c;
            while (!isdigit(c = getc())) if (c == '-') f = -1;
            while (x = (x << 1ll) + (x << 3ll) + (c ^ 48), isdigit(c = getc()));
            return x * f;
        }
        inline void rstr(char *str) {
            while (isspace(*str = getc()));
            while (!isspace(*++str = getc()))
                if (*str == EOF) break;
            *str = '';
        }
        template<typename T> 
            inline bool chkmin(T &x, T y) { return x > y ? (x = y, 1) : 0; }
        template<typename T>
            inline bool chkmax(T &x, T y) { return x < y ? (x = y, 1) : 0; }    
    }
    using namespace io;
    
    const int N = 2e5 + 1;
    
    int n, m, Fa[N];
    struct Edge { int u, v, a, b; } E[N];
    bool operator<(Edge a, Edge b) { return a.b < b.b; }
    
    namespace LCT {
    #define ls (ch[x][0])
    #define rs (ch[x][1])
    #define chk(x) (ch[fa[x]][1] == x)
    
        int top, stk[N];
        int ch[N][2], fa[N], mxid[N], id[N], rev[N];
    
        void init(int x, int y) {
            if (x > n) mxid[x] = id[x] = y;
        }
        bool irt(int x) {
            return x != ch[fa[x]][0] && x != ch[fa[x]][1]; 
        }
        void pu(int x) {
            mxid[x] = id[x];
            if (ls && E[mxid[x]].a < E[mxid[ls]].a) mxid[x] = mxid[ls];
            if (rs && E[mxid[x]].a < E[mxid[rs]].a) mxid[x] = mxid[rs];
        }
        void pd(int x) {
            if (rev[x]) {
                swap(ch[ls][0], ch[ls][1]); rev[ls] ^= 1;
                swap(ch[rs][0], ch[rs][1]); rev[rs] ^= 1;
                rev[x] = 0;
            }
        }
        void rot(int x) {
            int y = fa[x], z = fa[y], k = chk(x), tmp = ch[x][k ^ 1];
            ch[y][k] = tmp, fa[tmp] = y;
            if (!irt(y)) ch[z][chk(y)] = x; fa[x] = z;
            ch[x][k ^ 1] = y, fa[y] = x; 
            pu(y); pu(x);
        }
        void splay(int x) {
            stk[top = 1] = x; for (int i = x; !irt(i); i = fa[i]) stk[++top] = fa[i];
            while (top) pd(stk[top--]);
            while (!irt(x)) {
                int y = fa[x], z = fa[y];
                if (!irt(y)) 
                    if (chk(x) == chk(y)) rot(y);
                    else rot(x);
                rot(x);
            }
        }
        void access(int x) {
            for (int y = 0; x; x = fa[y = x]) splay(x), ch[x][1] = y, pu(x);
        }
        int findroot(int x) {
            access(x); splay(x); pd(x); while (ch[x][0]) x = ch[x][0], pd(x); splay(x); return x; 
        }
        void makeroot(int x) {
            access(x); splay(x); swap(ls, rs); rev[x] ^= 1;
        }
        void split(int x, int y) {
            makeroot(x); access(y); splay(y);
        }
        void link(int x, int y) {
            makeroot(x); fa[x] = y;
        }
        void cut(int x, int y) {
            split(x, y); ch[y][0] = fa[x] = 0;
        }
    }
    
    int find(int x) {
        return Fa[x] == x ? x : Fa[x] == find(Fa[x]);
    }
    void merge(int x, int y) {
        Fa[find(x)] = find(y);
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        file("P2387");
    #endif
        n = rint(), m = rint();
        For (i, 1, m) {
            E[i].u = rint(), E[i].v = rint(), E[i].a = rint(), E[i].b = rint(); 
        }
        sort(E + 1, E + 1 + m);
        For (i, 1, n + m) Fa[i] = i;
    
        For (i, n + 1, m + n) LCT::init(i, i - n);
    
        int ans = INF;
        For (i, 1, m) {
            //____;
            int u = E[i].u, v = E[i].v;
            if (LCT::findroot(u) == LCT::findroot(v)) {
                LCT::split(u, v);
                int Maxid = LCT::mxid[v];
                if (E[i].a < E[Maxid].a) {
                    LCT::cut(E[Maxid].u, Maxid + n); LCT::cut(Maxid + n, E[Maxid].v);
                    LCT::link(u, i + n); LCT::link(i + n, v);
                }
            } else {
                LCT::link(u, i + n); LCT::link(i + n, v);
            } 
            if (LCT::findroot(1) == LCT::findroot(n)) {
                LCT::split(1, n); int Maxid = LCT::mxid[n];
                chkmin(ans, E[i].b + E[Maxid].a);
            }
        }
        printf("%d
    ", ans == INF ? -1 : ans);
    }
    
    
    
  • 相关阅读:
    Vue 报错[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders
    常用的英语词汇
    增加个人形象气质
    网络基础
    MK-编辑器
    Nexus仓库构建
    POM的配置文件
    Dubbo_Admin安装
    dubbo管理控制台安装和使用
    Dubbox监控在服务器中的安装
  • 原文地址:https://www.cnblogs.com/cnyali-Tea/p/10459017.html
Copyright © 2011-2022 走看看