zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    DIY 作品 及 维修 不定时更新
    置顶,博客中所有源码 github
    openwrt PandoraBox PBR-M1 极路由4 HC5962 更新固件
    使用 squid 共享 虚拟专用网至局域网
    第一次参加日语能力测试 N5
    libx264 libfdk_aac 编码 解码 详解
    开发RTSP 直播软件 H264 AAC 编码 live555 ffmpeg
    MFC Camera 摄像头预览 拍照
    http2 技术整理 nginx 搭建 http2 wireshark 抓包分析 server push 服务端推送
    plist 图集 php 批量提取 PS 一个个切
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9832475.html
Copyright © 2011-2022 走看看