邻接矩阵是不错的一种图存储结构,但是,对于边数相对顶点较少的图,这种结构存在对存储空间的极大浪费。因此,找到一种数组与链表相结合的存储方法称为邻接表。
邻接表的处理方法是这样的:
(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;
}