1. 程式人生 > >Dijkstra + 鄰接表 + 佇列優化(最短路)

Dijkstra + 鄰接表 + 佇列優化(最短路)

//https://paste.ubuntu.com/p/R2dkdC5RDh/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <vector>
const int MAX = 10005 ;
const int inf =0x3f3f3f3f ;

using namespace std ;
//Dijkstra 佇列優化
struct qnode{
	int v ; // 節點編號
	int c ; // 到起點的距離
	qnode(int _v =0 ,int _c =0 ):v(_v),c(_c){
	} ;
	bool operator <(const qnode &r)const {
		return c>r.c ;
	}
};
struct Edge{
	int v;// 邊的終點和權值
	int w ;
	Edge(int _v=0 ,int _w =0):v(_v),w(_w){
		//初始化
	}
};

vector <Edge> e[MAX] ;
bool vis[MAX] ;
int dis[MAX] ;
int n ,m ;
void Dijkstra(int cur)
{
	memset(vis,false ,sizeof(vis)) ;
	for(int i = 1 ;i<=n ;i++)
	{
		dis[i] = inf ;
	}
	
	priority_queue<qnode> que ;
	// 按照節點到起點的距離大小作為出佇列的依據
	// 距離最近的先出
//	while(!que.empty())
//	{
//		// 初始化佇列
//		que.pop();
//	}
	dis[cur] = 0 ;
	que.push(qnode(cur,0)); // 將源點放入,距離為0
	qnode tmp ;
	while(!que.empty()) // 廣搜找通路
	{
		tmp = que.top();
		que.pop() ;
		int u = tmp.v ; // 找距離最近的編號
		
		if(vis[u])
		continue ;
		vis[u] = true  ;// 標記訪問過了
		// 下面是鬆弛操作 ;
		for(int i = 0 ;i<e[u].size();i++)
		{
			int v = e[u][i].v ;
			int w = e[u][i].w ;
			
			if(!vis[v] && dis[v] > dis[u]+w)
			{
				dis[v] = dis[u]+w ;
				que.push(qnode(v,dis[v]));
			}

		}

	}
	

}
void addedge(int u ,int v ,int w)
{
	e[u].push_back(Edge(v,w)) ;
	e[v].push_back(Edge(u,w)) ;
	return ;
}
int main()
{
	
	while(~scanf("%d%d",&n,&m))
	{
		if(n==0 && m==0)
		{
			break ;
		}
		while(m--)
		{
			int u ,v ,w ;
			scanf("%d%d%d",&u,&v,&w);
			addedge(u,v,w);
		}
		Dijkstra(1);
		printf("%d\n",dis[n]);
		
		for(int i = 1 ;i<=n ;i++)
		{
			e[i].clear();
		}
	}
	
	return 0 ;
}

鏈式前向星存邊+佇列優化

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std ;
const int MAX = 200005 ;

const int inf = 0x3f3f3f3f ;
struct Edge{
	int to ;
	int next ;
	int w ;
};
struct node{
	int u ;
	int d ;
	bool operator < (const node &x)const
	{
		return d > x.d ;
	}
};
Edge edge[MAX] ;
int n , m , s ;
int head[MAX]  ;
int cnt ;
int dis[MAX] ;
bool vis[MAX] ;

inline int read()
{
    int x=0,k=1; char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')k=-1;c=getchar();}
    while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*k;
}//快讀
void Add(int u , int v ,int w )
{
	cnt++ ;
	edge[cnt].next = head[u] ;
	edge[cnt].to = v ;
	edge[cnt].w = w  ;
	head[u] = cnt ;
}
inline void Dijkstra(int s)
{
    priority_queue<node> q ;
	for(int i = 1 ; i<=n ;i++)
	{
		dis[i] = inf ;
		vis[i] = false ;
	}

	dis[s] = 0 ;
	q.push({s,0});
	while(!q.empty())
	{
		node tmp = q.top() ;
		q.pop();
		int u = tmp.u ;
		if(vis[u])
		continue ;
		vis[u] = true ;
		for(int i = head[u] ; i ; i = edge[i].next)
		{
			int v = edge[i].to ;
			int d = edge[i].w ;
			if(dis[v] > dis[u] +d)
			{
				dis[v] = dis[u]+d ;
				if(!vis[v])
				{
					q.push({v,dis[v]});
				}
			}
		}


	}

}
int main()
{
    //freopen("in.txt","r",stdin);
	while(~scanf("%d%d",&n,&m))
	{
        cnt = 0 ;
        if(n==0 && m==0)
        break ;
        for(int i = 0 ; i<= n ;i++)
        head[i] = 0 ;
        memset(edge,0,sizeof(edge));
        for(int i = 1 ; i<=m ;i++)
        {
            int u , v ,w ;
            u = read() ;
            v = read() ;
            w = read() ;
            Add(u,v,w) ;
            Add(v,u,w) ;
        }
        Dijkstra(1);

        printf("%d\n",dis[n]);
	}


	return 0 ;
}