码迷,mamicode.com
首页 > 其他好文 > 详细

[模板]链式向前星

时间:2021-04-08 14:03:54      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:参考   rds   vector   namespace   car   通过   line   code   sed   

我以前和你一样也是个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\n", 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\n", dist[n] - dist[1]);

    return 0;
}
vector版本,供参考

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

技术图片

 

[模板]链式向前星

标签:参考   rds   vector   namespace   car   通过   line   code   sed   

原文地址:https://www.cnblogs.com/Gaomez/p/14631311.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!