• NOIP模拟 path


    题目原文:

    企鹅豆豆即将要去考长跑了,但是作为一只企鹅,长跑自然比不过鸵鸟和鸡。为了公平起见,教练告诉豆豆,他可以从 K 个指定地点中选择两个不同的地点分别作为起点和终点来考试.考试地图是一个由 N 个点 M 条边组成的没有重边和自环的连通无向图,一条边的长度为 Ai 。豆豆想知道他的长跑考试最少需要跑多远。

    【数据范围】
    对于 30% 的数据,K≤4;
    对于另外 10% 的数据,K=N;
    对于另外 30% 的数据,M=N-1;
    对于 100% 的数据,1≤N,M≤100000;T≤5;1≤K≤n;1≤边长≤100000。

    题目分析:

    就是求图中最近的两个特殊点之间的距离。

    • 乱搞版:对每个特殊点进行一遍dijkstra,一遇到其他特殊点就break,更新答案。数据没有刻意去卡,加上部分分的优化勉强能卡掉。
    • 高大上的正解: 将k个点编号1...k,枚举编号的二进制的每一位,将这一位为1的点连边S(作为起点),为0的点连边T(作为终点),这样跑(log(k))次dijkstra即可得到答案。总复杂度(O(nlog(n)log(k))),还是尽量加上部分分的优化。

    code

    乱搞版:

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    
    namespace IO{
        inline int readint(){
            int i = 0, f = 1; char ch = getchar();
            for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
            if(ch == '-') f = -1, ch = getchar();
            for(; ch >= '0' && ch <= '9'; ch = getchar()) i = (i << 3) + (i << 1) + (ch - '0');
            return i * f;
        }
        inline ll readll(){
            ll i = 0, f = 1; char ch = getchar();
            for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
            if(ch == '-') f = -1, ch = getchar();
            for(; ch >= '0' && ch <= '9'; ch = getchar()) i = (i << 3) + (i << 1) + (ch - '0');
            return i * f;
        }
        inline void wrint(int x){
            if(x < 0) putchar('-'), x = -x;
            if(x > 9) wrint(x / 10);
            putchar(x % 10 + '0');
        }
        inline void wrll(ll x){
            if(x < 0) putchar('-'), x = -x;
            if(x > 9) wrll(x / 10);
            putchar(x % 10 + '0');
        }
    }using namespace IO;
    
    const int N = 1e5 + 5, M = 1e5 + 5, OO = 0x3f3f3f3f;
    int n, m, k, ecnt, adj[N], go[M << 1], nxt[M << 1], T;
    vector<int> keyPoint;
    typedef pair<ll, int> P;
    priority_queue<P, vector<P>, greater<P> > que;
    bool key[N];
    ll len[M << 1], dis[N], minn;
    
    inline void addEdge(int u, int v, ll w){ nxt[++ecnt] = adj[u], adj[u] = ecnt, go[ecnt] = v, len[ecnt] = w;}
    
    inline void solve(){
        ll ret = OO;
        for(int i = 0; i < k; i++){
            int u = keyPoint[i];
            memset(dis, OO, sizeof dis), dis[u] = 0;
            while(!que.empty()) que.pop(); que.push(P(0, u));
            while(!que.empty()){
                P t = que.top(); que.pop();
                if(t.second != u && key[t.second]){
                    ret = min(ret, t.first);
                    break;
                }
                for(int e = adj[t.second]; e; e = nxt[e]){
                    int v = go[e];
                    if(dis[v] > t.first + len[e]){
                        dis[v] = t.first + len[e];
                        que.push(P(dis[v], v));
                    }
                }
            }
        }
        wrll(ret), putchar('
    ');
    }
    
    int main(){
        freopen("h.in", "r", stdin);
        T = readint();
        while(T--){
            n = readint(), m = readint();
            memset(adj, 0, sizeof adj), ecnt = 0, keyPoint.clear(), memset(key, 0, sizeof key), minn = OO;
            for(int i = 1; i <= m; i++){
                int u = readint(), v = readint();
                ll w = readll(); minn = min(minn, w);
                addEdge(u, v, w), addEdge(v, u, w);
            }
            k = readint();
            for(int i = 1; i <= k; i++){ int x; keyPoint.push_back(x = readint()), key[x] = true;}
            if(k == n){ wrll(minn), putchar('
    ');}
            else solve();
        }
        return 0;
    }
    

    正解:

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    
    namespace IO{
        inline int readint(){
            int i = 0, f = 1; char ch = getchar();
            for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
            if(ch == '-') f = -1, ch = getchar();
            for(; ch >= '0' && ch <= '9'; ch = getchar()) i = (i << 3) + (i << 1) + (ch - '0');
            return i * f;
        }
        inline ll readll(){
            ll i = 0, f = 1; char ch = getchar();
            for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
            if(ch == '-') f = -1, ch = getchar();
            for(; ch >= '0' && ch <= '9'; ch = getchar()) i = (i << 3) + (i << 1) + (ch - '0');
            return i * f;
        }
        inline void wrint(int x){
            if(x < 0) putchar('-'), x = -x;
            if(x > 9) wrint(x / 10);
            putchar(x % 10 + '0');
        }
        inline void wrll(ll x){
            if(x < 0) putchar('-'), x = -x;
            if(x > 9) wrll(x / 10);
            putchar(x % 10 + '0');
        }
    }using namespace IO;
    
    const int N = 1e5 + 5, M = 1e5 + 5, OO = 0x3f3f3f3f;
    int n, m, k, ecnt, adj[N], go[M << 1], nxt[M << 1], T;
    vector<int> keyPoint;
    typedef pair<ll, int> P;
    priority_queue<P, vector<P>, greater<P> > que;
    ll len[M << 1], dis[N], num[N], minn;
    
    inline void addEdge(int u, int v, ll w){ nxt[++ecnt] = adj[u], adj[u] = ecnt, go[ecnt] = v, len[ecnt] = w;}
    
    inline void solve(){
        ll ret = OO;
        for(int i = 0; (1 << i) <= k; i++){
            memset(dis, OO, sizeof dis);
            while(!que.empty()) que.pop();
            for(int j = 0; j < keyPoint.size(); j++)
                if((1 << i) & num[keyPoint[j]]) dis[keyPoint[j]] = 0, que.push(P(0, keyPoint[j]));
            while(!que.empty()){
                P t = que.top(); que.pop();
                if(num[t.second] && !((1 << i) & num[t.second])){ ret = min(ret, t.first); break; }
                for(int e = adj[t.second], v; e; e = nxt[e]){
                    if(dis[v = go[e]] > t.first + len[e]){
                        dis[v] = t.first + len[e];
                        que.push(P(dis[v], v));
                    }
                }
            }
        }
        wrll(ret), putchar('
    ');
    }
    
    int main(){
        freopen("h.in", "r", stdin);
        T = readint();
        while(T--){
            n = readint(), m = readint();
            memset(adj, 0, sizeof adj), ecnt = 0, keyPoint.clear(), memset(num, 0, sizeof num), minn = OO;
            for(int i = 1; i <= m; i++){
                int u = readint(), v = readint();
                ll w = readll(); minn = min(minn, w);
                addEdge(u, v, w), addEdge(v, u, w);
            }
            k = readint();
            for(int i = 1; i <= k; i++){ int x; keyPoint.push_back(x = readint()), num[x] = i;}
            if(k == n) { wrll(minn), putchar('
    ');}
            else solve();
        }
        return 0;
    }
    
  • 相关阅读:
    关于i 标签盛放背景图像
    关于首行缩进
    复选框样式自定义
    创建对象的两种方法
    SpringBoot项目中常见的注解
    微服务 第一章:Idea快速创建SpringBoot项目
    Exception in thread "Thread-1" java.util.ConcurrentModificationException 异常原因和解决方法
    《改善java代码》第四章:改善关于字符串的代码
    IDEA忽略不必要提交的文件
    Git分支管理
  • 原文地址:https://www.cnblogs.com/CzYoL/p/7668644.html
Copyright © 2020-2023  润新知