Til the Cows Come Home:Dijkstra算法,用优先队列

问题描述:
兔子很热爱学习,为了多学习她希望可以找最快的路线去上学。她的城市里有N个(2 <= N <= 1000)个地铁站,编号分别为1…N。兔子家在1号地铁站旁边,学校是N号地铁站。地铁站之间共有M (1 <= M <= 2000)条双向路径。兔子现在在1号地铁站,她希望知道到学校最短需要多少时间。可以保证兔子能到达学校。忽略换乘地铁的等待时间
Input
第一行:m和n
接下来的m行:每一行有x,y,z三个整数。代表x站到y站或者y站到x站需要z分钟(1<=z<=100)
Output
兔子到学校最少需要多少时间。
直接思路:
直接最短路径,有一个地方,题目没有说明白,就是从一个地方到另一个地方可能有用时不一样的,要取最小的。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <stdio.h>
#include <queue>
using namespace std;
struct Node {
    int num;	//编号 
    int d;		//从起点到该点的最短路程 
    bool operator < (const Node &a) const {
        return d>a.d;//最小值优先
    }
};

const int _inf = 0x3f3f3f3f;
const int N = 1010;

int m,n;
int map[N][N];
int dis[N];//如果要记录路线,还可以加一个pre[N]记录前驱 
int vis[N];

void Dijkstra(int s)
{
	for(int i = 1; i <= n; i++)
		dis[i] = _inf;
//	for(int i = 1; i <= n; i++)		//本题不需要记录前驱
//		pre[i] = -1;
	dis[s] = 0;
	priority_queue<Node> q;
	Node temp = {s,dis[s]};
	q.push(temp);
	while(!q.empty())
	{
		int u = q.top().num;
		q.pop();
		if(vis[u])//如果被标记过,直接跳过
			continue;
		vis[u] = true;
		for(int v = 1; v <= n; v++)
		{
			if(!vis[v]&&map[u][v]&&dis[u]+map[u][v] < dis[v])
			{
				dis[v] = dis[u] + map[u][v];
//				pre[v] = u;	//前驱
				temp.num = v;
				temp.d = dis[v];
				q.push(temp);
			}
		}
	}
}

int main()
{
	int x,y,z;
	while(scanf("%d%d",&m,&n)!=EOF)
	{
		memset(map,0,sizeof(map));
		memset(vis,0,sizeof(vis));
		for(int i = 0; i < m; i++)
		{
			scanf("%d%d%d",&x,&y,&z);
			if(!map[x][y])		//这就那个小陷阱
			{
				map[x][y] = map[y][x] = z;
			}
			else
			{
				if(map[x][y] > z)
				map[x][y] = map[y][x] = z;
			}
			
		}
		Dijkstra(1);
		printf("%d\n",dis[n]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_46687179/article/details/105916120