• Luogu 2573 [SCOI2012]滑雪


    BZOJ 2753

    首先可以按照题目要求的把所有的有向边建出来,然后进去广搜就可以求出第一问的解,然后考虑如何求解第二问,我们把所有搜到的边按照到达的点的高度位第一关键字,边的长度为第二关键字排序之后跑$kruskal$,这样子得到的最小生成树权值就是第二问所求的最大值。

    考虑一下这样子为什么正确,首先“时间胶囊”的返回形式让答案一定是一棵生成树的权值,但是直接跑最小生成树可能会造成有一些点不能走到的情况,所以我们搜出所有的可能能到达的点,然后按照点的海拔高度先排序之后就一定能保证所有点都能走到,这样子求出来的生成树也一定是最小代价的。

    时间复杂度$O(mlogm)$。

    Code:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    using namespace std;
    typedef long long ll;
    
    const int N = 1e5 + 5;
    const int M = 1e6 + 5;
    
    int n, m, num = 0, tot = 0, head[N], edgeNum = 0, ufs[N];
    ll h[N];
    bool vis[N];
    
    struct Edge {
        int to, nxt;
        ll val;
    } e[M << 1];
    
    inline void add(int from, int to, ll val) {
        e[++tot].to = to;
        e[tot].val = val;
        e[tot].nxt = head[from];
        head[from] = tot;
    }
    
    struct Pathway {
        int u, v;
        ll val;
        
        friend bool operator < (const Pathway &x, const Pathway &y) {
            if(h[x.v] != h[y.v]) return h[x.v] > h[y.v];
            else return x.val < y.val;
        }
        
    } pat[M << 1];
    
    template <typename T>
    inline void read(T &X) {
        X = 0; char ch = 0; T op = 1;
        for(; ch > '9'|| ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    inline void init() {
        for(int i = 1; i <= n; i++) ufs[i] = i;
    }
    
    int find(int x) {
        return ufs[x] == x ? x : ufs[x] = find(ufs[x]);
    } 
    
    queue <int> Q;
    void bfs() {
        Q.push(1); 
        vis[1] = 1; num = 1;
        for(; !Q.empty(); ) {
            int x = Q.front(); Q.pop();
            for(int i = head[x]; i; i = e[i].nxt) {
                int y = e[i].to;
                pat[++edgeNum] = (Pathway) {x, y, e[i].val};
                if(!vis[y]) {
                    vis[y] = 1; ++num;
                    Q.push(y);
                }
            }
        }
    }
    
    inline ll kruskal() {
        init();
        sort(pat + 1, pat + 1 + edgeNum);
        ll res = 0LL;
        for(int cnt = 0, i = 1; i <= edgeNum; i++) {
            int u = find(pat[i].u), v = find(pat[i].v);
            if(u == v) continue;
            ufs[u] = v;
            ++cnt;
            res += pat[i].val;
            if(cnt >= num - 1) break;
        }
        return res;
    }
    
    int main() {
    //    freopen("3.in", "r", stdin);
        
        read(n), read(m);
        for(int i = 1; i <= n; i++) read(h[i]);
        for(int i = 1; i <= m; i++) {
            int x, y; ll v;
            read(x), read(y), read(v);
            if(h[x] >= h[y]) add(x, y, v);
            if(h[x] <= h[y]) add(y, x, v);
        }
        
        bfs();
        
        printf("%d %lld
    ", num, kruskal());
        return 0;
    }
    View Code
  • 相关阅读:
    List Available DBCC Commands
    DBCC
    Oracle Shared Pool机制之——Latches, Locks, Pins and Mutexes
    新春寄语——令人期待的2018
    Oracle Shared Pool之Library Cache
    Linux NTP服务配置 for Oracle RAC
    Oracle 12c启动时PDBs的自动打开
    Oracle RAC时间同步(NTP/CTSS)
    Oracle 11g后台进程一览表
    Selenium WebDriver-通过断言页面是否存在某些关键字来确定页面按照预期加载
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9832475.html
Copyright © 2020-2023  润新知