c++图论vector邻接表与链式前向星性能差异

一句话概括:如果以后能用链式前向星的话(知道边数的情况下)就尽量用链式前向星别用vector邻接表

因为我以前学图论的时候,先接触到的就是vector邻接表的写法,所以后来一直都是用vector邻接表的写法,后来也接触到了链式前向星的写法,然后那时候也了解到了vector邻接表与链式前向星有内存性能上的差异,因为vector扩充时是默认多申请2倍空间,所以一些特别变态的题目可能会卡内存只能用链式前向星的写法写。不过当时也没特别在意,也想着到时候看边数量特别大的话再说,vector邻接表也写惯了,可是最近居然被卡了两道时间的题目,让我意识到可能链式前向星写法与vector写法还有时间上的差距,我猜与STL实现上有关。(更新:最近看STL源码剖析,vector每次扩充都要copy一遍元素到新内存块,肯定会慢很多的)

我就拿其中一题来举例吧

 

问题描述

农夫约翰正在针对一个新区域的牛奶配送合同进行研究。他打算分发牛奶到T个城镇(标号为1..T),这些城镇通过R条标号为(1..R)的道路和P条标号为(1..P)的航路相连。

每一条公路i或者航路i表示成连接城镇Ai(1<=A_i<=T)和Bi(1<=Bi<=T)代价为Ci。每一条公路,Ci的范围为0<=Ci<=10,000;由于奇怪的运营策略,每一条航路的Ci可能为负的,也就是-10,000<=Ci<=10,000。

每一条公路都是双向的,正向和反向的花费是一样的,都是非负的。

每一条航路都根据输入的Ai和Bi进行从Ai->Bi的单向通行。实际上,如果现在有一条航路是从Ai到Bi的话,那么意味着肯定没有通行方案从Bi回到Ai。

农夫约翰想把他那优良的牛奶从配送中心送到各个城镇,当然希望代价越小越好,你可以帮助他嘛?配送中心位于城镇S中(1<=S<=T)。

输入格式

输入的第一行包含四个用空格隔开的整数T,R,P,S。

### 关于邻接表链式前向星数据结构例题实现 #### 使用邻接表表示图并解决最短路径问题 对于给定的一个无权有向图,使用邻接表来表示该图,并求解从源点到其他各顶点的最短距离。 ```cpp #include <iostream> #include <vector> #include <queue> using namespace std; const int MAXN = 1e5 + 7; int dist[MAXN]; bool vis[MAXN]; // 定义边结构体 struct Edge { int to, next; } edge[MAXN * 2]; // 假设最多有MAXN*2条边 int head[MAXN], cnt; // head数组记录每个节点的第一条出边编号;cnt用于计数当前已有的边数量 void addEdge(int from, int to) { // 添加一条from->to方向上的边 edge[++cnt].to = to; edge[cnt].next = head[from]; head[from] = cnt; } void bfs(int startNode) { queue<int> q; memset(dist, -1, sizeof(dist)); dist[startNode] = 0; q.push(startNode); while (!q.empty()) { int cur = q.front(); q.pop(); for (int i = head[cur]; ~i; i = edge[i].next) { int v = edge[i].to; if (dist[v] == -1) { dist[v] = dist[cur] + 1; q.push(v); } } } } ``` 这段代码展示了如何利用邻接表构建一张简单的无权有向图以及通过广度优先搜索算法计算起始节点到达其余各个节点之间的最小步数[^1]。 #### 利用链式前向星处理加权图中的最短路问题 下面的例子说明了怎样运用链式前向星存储带权重的边信息,并借助Dijkstra算法找出单源最短路径: ```cpp #include <cstring> #include <algorithm> #define INF 0x3f3f3f3f using namespace std; typedef pair<int,int> PII; const int N=1e5+10,M=N<<1; int n,m,S,T,d[N]; PII e[M]; int h[N],ne[M],w[M],idx; bool st[N]; inline void add(int a,int b,int c){ e[idx]=make_pair(b,c),ne[idx]=h[a],h[a]=idx++; } void dijkstra(){ memset(d,INF,sizeof d); priority_queue<PII,vector<PII>,greater<>> heap; d[S]=0; heap.push({d[S],S}); while(heap.size()){ auto t=heap.top(); heap.pop(); int ver=t.second,dis=t.first; if(st[ver]) continue; st[ver]=true; for(int i=h[ver];~i;i=ne[i]){ int j=e[i].first; if(d[j]>dis+w[i]){ d[j]=dis+w[i]; heap.push({d[j],j}); } } } } ``` 此部分实现了基于链式前向星的方式保存每条边上附带的成本值,并且采用了堆优化版迪杰斯特拉(Dijkstra)算法去查找由指定起点出发至其它任意终点间的最优路线长度[^2]。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值