邻接表实现迪杰特拉斯最短路算法
2020-04-02 18:36
986 查看
邻接矩阵是不错的一种图存储结构,但是,对于边数相对顶点较少的图,这种结构存在对存储空间的极大浪费。因此,找到一种数组与链表相结合的存储方法称为邻接表。
邻接表的处理方法是这样的:
(1)图中顶点用一个一维数组存储,当然,顶点也可以用单链表来存储,不过,数组可以较容易的读取顶点的信息,更加方便。
(2)图中每个顶点vi的所有邻接点构成一个线性表,由于邻接点的个数不定,所以,用单链表存储,无向图称为顶点vi的边表,有向图则称为顶点vi作为
弧尾的出边表。
缺点:易超时且不灵活,只是邻接矩阵减少空间使用的一种优化
#include<iostream> #include<queue> #include<stdio.h> #include<string.h> using namespace std; const int N = 10005; int h[N], d[N], s[N], ne[N], idex, dist[N]; void add(int a, int b, int c) { ne[idex] = h[a];//让next数组记录之前头节点的位置 h[a] = idex;//头节点的当下位置 s[idex] = c;//记录边长 d[idex++] = b;//记录所到达的位置 } queue<int>q; void dij() { q.push(1); dist[1] = 0; while (q.size()) { int t = q.front(); q.pop(); for (int i = h[t]; i != -1; i = ne[i]) { int j = d[i]; if (dist[j] > dist[t] + s[i]) { dist[j] = dist[t] + s[i]; q.push(j);//更新节点 } } } } int main(void) { int m, n; cin >> n >> m;//n个点m条边 memset(dist, 0x3f3f3f3f, sizeof(dist)); memset(h, -1, sizeof(h)); for (int i = 0; i < m; i++)//依次输入m条边 { int a, b, c; scanf("%d%d%d",&a,&b,&c);//a到b的距离是c add(a, b, c); } dij(); if(dist[n]>0x3f3f3f3f/2) dist[n]=-1; printf("%d", dist[n]); }
堆优化版本+邻接表
#include <iostream> #include <cstdio> #include <queue> #include <vector> #include <cstring> using namespace std; const int MAXN=1000000; vector<int> g[605];//邻接表,g[i]一次存储与i邻接的边的下标,方便快速查找 bool vis[605];//标记数组 int low[605],n,m;//当前最短距离 struct Edge{//边类 int from,to,dis; }; vector<Edge> edge;//存储边的情况 struct Node{//用于优先队列中的节点 int d,u; bool operator<(const Node &b)const{ return this->d>b.d; } }; void dijkstra(){ for(int i=0;i<=n;++i) low[i]=MAXN;//初始化 low[1]=0; memset(vis,false,sizeof(vis)); priority_queue<Node> q;//用了一个优先列队个人觉得还是得遍历一遍没咋优化 q.push((Node){0,1}); while(!q.empty()){ Node x=q.top();//快速找当前最短距离点 q.pop(); int u=x.u; if(vis[u]) continue;//如果该点已经为最优,则忽略 vis[u]=true; for(int i=0;i<g[u].size();++i){//更新 Edge &e=edge[g[u][i]]; if(low[e.to]>low[u]+e.dis){ low[e.to]=low[u]+e.dis; q.push((Node){low[e.to],e.to}); } } } } int main() { scanf("%d%d",&n,&m); while(m--){ int a,b,c; scanf("%d%d%d",&a,&b,&c); edge.push_back((Edge){a,b,c}); g[a].push_back(edge.size()-1); } dijkstra(); if(low[n]>=MAXN) printf("-1\n"); else printf("%d\n",low[n]); return 0; }
这种简化版有点问题留个坑弄明白后改过来
#include <bits/stdc++.h> using namespace std; const int N=11000; int dis[11000]; vector<int>len[N]; vector<int>edge[N]; struct cmp{ bool operator()(int x,int y){ return dis[x]>dis[y]; } }; void dij(int u){ priority_queue<int,vector<int>,cmp >heap; heap.push(u); dis[u] = 0; while(!heap.empty()){ int u = heap.top(); int i = -1; for(auto v:edge[u]){ i ++; if(dis[v]>dis[u]+len[u][i]){ dis[v] = dis[u]+len[u][i]; heap.push(v); } } heap.pop(); } } int main() { // freopen("a.txt","r",stdin); ios::sync_with_stdio(0); int i,n,m; while(cin>>n>>m) { for(i = 1;i <= n;i ++) dis[i] = 1e9; for(i = 1;i <= n;i ++) edge[i].clear(); for(i = 1;i <= n;i ++) len[i].clear(); for(i = 1;i <= m;i ++){ int u,v,l; cin>>u>>v>>l; edge[u].push_back(v); edge[v].push_back(u); len[u].push_back(l); len[v].push_back(l); } dij(1); if(dis[n]>0x3f3f3f3f/2) dis[n]=-1; cout<<dis[n]<<endl; } return 0; }
- 点赞
- 收藏
- 分享
- 文章举报
相关文章推荐
- 最短路算法(Dijkstra、Bellman-Ford、SPFA邻接表实现)
- 邻接表实现最短路算法
- 邻接表图java实现
- 图的邻接表的实现(链表+数组)
- 关于图的邻接表C++实现
- 邻接表实现prim
- 第十一周项目实践2 用邻接表存储的图来实现基本应用
- 最小生成树Prim算法实现(采用邻接表存储)C++实现
- 第十二周项目二(操作用邻接表实现的图)
- 图的遍历和生成树求解实现|图遍历,生成树,实现,邻接矩阵,邻接表,深度广度遍历,最小生成树
- 使用邻接表实现基数排序
- 图论基础(邻接矩阵,邻接表,深度优先遍历,连通分量)的实现
- 转自啊哈磊--数组实现邻接表
- 图的邻接表存储(C语言实现)
- 用邻接表或vector实现存边以及具体如何调用[模板]
- 巧妙的邻接表(数组实现)
- 十字链表 邻接表实现各种操作
- 图的邻接表存储与深度优先遍历代码实现
- 带权重无向图——C++实现创建邻接表,DFS深度遍历,BFS广度遍历
- 一个我认为比较好的Spfa模板(使用邻接表和队列实现)