邻接表实现迪杰特拉斯最短路算法

邻接矩阵是不错的一种图存储结构,但是,对于边数相对顶点较少的图,这种结构存在对存储空间的极大浪费。因此,找到一种数组与链表相结合的存储方法称为邻接表。
邻接表的处理方法是这样的:
(1)图中顶点用一个一维数组存储,当然,顶点也可以用单链表来存储,不过,数组可以较容易的读取顶点的信息,更加方便。
(2)图中每个顶点vi的所有邻接点构成一个线性表,由于邻接点的个数不定,所以,用单链表存储,无向图称为顶点vi的边表,有向图则称为顶点vi作为邻接表实现迪杰特拉斯最短路算法_第1张图片弧尾的出边表。
缺点:易超时且不灵活,只是邻接矩阵减少空间使用的一种优化

#include
#include
#include
#include
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 
#include 
#include 
#include 
#include 
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 

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;
}

你可能感兴趣的:(基础算法)