zoukankan      html  css  js  c++  java
  • 洛谷

    https://www.luogu.org/problem/P1462

    感觉,要二分最大收费权的城市,把小于等于它的全部插进去,Dijkstra一下求出最小的血量。这样感觉太暴力了。

    考虑只有10000个城市,sort一下,每条无向边都由排名靠后的城市插入。按收费顺序插入城市,直到并查集中1和n连通,来一次Dijkstra求出所需的血量。

    假如所需血量已经>=b,说明不合法。

    这个时候插入下一个城市及其连通的边,考虑会发生什么改变?首先到达这个城市的最短距离必定是从连出城市走对应路径过来的。

    其次它可能会对整个图进行一次更新。所以这个复杂度也是惊人。

    所以还是二分城市,要log1e5=15,插入对应的边5e4,跑一次Dijkstra要5e4log5e4=8e5,小得很。


    想着至少要过一半吧,没想到一发就全AC了。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int MAXN = 1e4 + 5, INF = 0x3f3f3f3f;
    
    struct Edge {
        int v, w;
        Edge() {}
        Edge(int v, int w): v(v), w(w) {}
    };
    bool vis[MAXN];
    int dis[MAXN];
    vector<Edge> G[MAXN];
    
    int fa[MAXN];
    int find(int x) {
        return fa[x] == x ? x : fa[x] = find(fa[x]);
    }
    
    void merge(int x, int y) {
        int fx = find(x), fy = find(y);
        fa[fy] = fx;
    }
    
    struct City {
        int id, f;
        bool operator<(const City &c)const {
            return f < c.f;
        }
    } city[MAXN];
    
    int n, b;
    
    void Init() {
        for(int i = 0; i <= n; ++i)
            fa[i] = i;
        memset(vis, 1, sizeof(vis[0]) * (n + 1));
        memset(dis, INF, sizeof(dis[0]) * (n + 1));
    }
    
    void AddCity(int Ceil) {
        for(int i = 1; i <= Ceil; ++i) {
            int u = city[i].id;
            vis[u] = 0;
            for(auto ei : G[u])
                merge(u, ei.v);
        }
    }
    
    priority_queue<pair<int, int> > pq;
    int Dijkstra(int s) {
        pq.push({0, 1});
        dis[1] = 0;
        while(!pq.empty()) {
            int u = pq.top().second;
            pq.pop();
            if(vis[u])
                continue;
            vis[u] = 1;
            for(auto ei : G[u]) {
                int v = ei.v, w = ei.w;
                if(!vis[v] && dis[u] + w < dis[v]) {
                    dis[v] = dis[u] + w;
                    pq.push({-dis[v], v});
                }
            }
        }
        return dis[n];
    }
    
    bool check(int Ceil) {
        Init();
        AddCity(Ceil);
        if(find(1) != find(n))
            return false;
        int res = Dijkstra(1);
        return res < b;
    }
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        int m;
        scanf("%d%d%d", &n, &m, &b);
        for(int i = 1; i <= n; ++i) {
            scanf("%d", &city[i].f);
            city[i].id = i;
        }
        sort(city + 1, city + 1 + n);
        for(int i = 1; i <= m; ++i) {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            G[u].emplace_back(Edge(v, w));
            G[v].emplace_back(Edge(u, w));
        }
        int L = 1, R = n, M;
        while(1) {
            M = L + R >> 1;
            if(L == M) {
                if(check(L)) {
                    printf("%d
    ", city[L].f);
                    return 0;
                } else if(check(R)) {
                    printf("%d
    ", city[R].f);
                    return 0;
                }
                puts("AFK");
                return 0;
            }
            if(check(M))
                R = M;
            else
                L = M + 1;
        }
    }
    
  • 相关阅读:
    一次网络IO优化的讨论
    服务器框架回顾
    一个小工具:DebugFile
    TPO-23 C2 Advice on choosing courses
    TPO-23 C1 Post a student announcement
    TPO-22 C2 Revise a music history paper
    TPO-22 C1 Complain about a biased article
    TPO-21 C2 Which elective courses to take
    TPO-20-Apply for the undergraduate research fund
    TPO-21 C1 Find a building for orientation
  • 原文地址:https://www.cnblogs.com/Yinku/p/11343565.html
Copyright © 2011-2022 走看看