• [模板]链式向前星


    我以前和你一样也是个vectorer,直到我膝盖中了一TLE.

    Invitation Cards 这道题目,8s的时限,1e6的数据,只不过是跑了两边DIjkstra,vector超时,而向前星只需要2s.

    同样是邻接表存图,链式向前星虽然没有vector那么简洁,但是速度会有明显提升,并且许多操作两者是有共同写法的,有必要学一下.

    使用链式向前星存图:

    // N - 节点数, M - 边数
    struct E{
        int to, wei, nxt;    // nxt即next, 但后者似乎是保留名称
    }e[M];
    int head[N], ind = 1;
    // 下面添加一条由x指向y, 权为w的有向边
    inline void add(int x, int y, int w){
        e[ind].to = y;
        e[ind].wei = w;
        e[ind].nxt = head[x];
        head[x] = ind++;
    }

    读取图上信息:

    // 遍历以x为起点的所有边
    for(int i = head[cur.to]; i; i = e[i].nxt){
        // e[i].to - 当前边指向的终点
        // e[i].wei - 当前边的权
        // ...operations...
    }

    给出一道单源最短路径的模板题,数据范围达到了3e6.

    这里用链式向前星写一个Dijkstra,我的实现方法除了建图与读图部分外与vector版本基本相同.

    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <queue>
    using namespace std;
    
    struct E{
        int to, wei, nxt;
    }e[150010];
    struct Q{  // queue_element
        int to, wei;
        bool operator<(const Q &other)const {return wei > other.wei;}
    };
    priority_queue<Q> q;
    int n, m, head[30010], ind = 1, dist[30010];
    
    inline void add(int x, int y, int w){
        e[ind].to = y;
        e[ind].wei = w;
        e[ind].nxt = head[x];
        head[x] = ind++;
    }
    
    int main(){
        memset(dist, -1, sizeof(dist));
        scanf("%d%d", &n, &m);
        while(m--){
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            add(a, b, c);
        }
    
        q.push({1, 0});
        while(!q.empty()){
            Q cur = q.top();
            q.pop();
            if(dist[cur.to] != -1) continue;
    
            dist[cur.to] = cur.wei;
            for(int i = head[cur.to]; i; i = e[i].nxt)
                if(dist[e[i].to] == -1)
                    q.push({e[i].to, cur.wei + e[i].wei});
        }
    
        printf("%d
    ", dist[n] - dist[1]);
    
        return 0;
    }

    (后两个是时间(ms)和空间(MB))

    再给出一份我写的vector版本供参考.

    可以说是非常落魄了,只有加了快读后才能通过.

    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <queue>
    #include <vector>
    using namespace std;
    
    struct E{   // 这里E和Q可以通用
        int to, wei;
        bool operator<(const E& other) const {return wei > other.wei;}
    };
    vector<E> e[30010];
    priority_queue<E> q;
    int n, m, dist[30010];
    
    inline int read() {
        char ch = getchar();
        int x = 0, f = 1;
        while (ch > '9' || ch < '0') {
            if (ch == '-') f = -1;
            ch = getchar();
        }
        while (ch >= '0' && ch <= '9') {
            x = x * 10 + ch - '0';
            ch = getchar();
        }
        return x * f;
    }
    
    int main(){
        memset(dist, -1, sizeof(dist));
        n = read(), m = read();
        while(m--){
            int a, b, c;
            a = read(), b = read(), c = read();
            e[a].push_back({b, c});
        }
    
        q.push({1, 0});
        while(!q.empty()){
            E cur = q.top();
            q.pop();
            if(dist[cur.to] != -1) continue;
    
            dist[cur.to] = cur.wei;
            for(vector<E>::iterator i = e[cur.to].begin(); i != e[cur.to].end(); i++)
                if(dist[i->to] == -1) q.push({i->to, cur.wei + i->wei});
        }
    
        printf("%d
    ", dist[n] - dist[1]);
    
        return 0;
    }
    vector版本,供参考

    并且性能相比于链式向前星几乎是腰斩.

  • 相关阅读:
    复杂json格式转化为javabean
    lambda常用方法
    solr设置分片和副本
    Python之Scrapy爬虫框架安装及简单使用
    40多个纯CSS绘制的图形
    windows下自动启动Redis隐藏命令行窗口
    用Webpack构建Vue项目
    上传本地代码到gitHub过程详解
    html/css常用合集
    数据库索引与b+树
  • 原文地址:https://www.cnblogs.com/Gaomez/p/14631311.html
Copyright © 2020-2023  润新知