【一只蒟蒻的刷题历程】 【PAT】 A1030 旅行计划

A traveler’s map gives the distances between cities along the highways, together with the cost of each highway. Now you are supposed to write a program to help a traveler to decide the shortest path between his/her starting city and the destination. If such a shortest path is not unique, you are supposed to output the one with the minimum cost, which is guaranteed to be unique.

Input Specification:

Each input file contains one test case. Each case starts with a line containing 4 positive integers N, M, S, and D, where N (≤500) is the number of cities (and hence the cities are numbered from 0 to N−1); M is the number of highways; S and D are the starting and the destination cities, respectively. Then M lines follow, each provides the information of a highway, in the format:

City1 City2 Distance Cost

where the numbers are all integers no more than 500, and are separated by a space.

Output Specification:

For each test case, print in one line the cities along the shortest path from the starting point to the destination, followed by the total distance and the total cost of the path. The numbers must be separated by a space and there must be no extra space at the end of output.

Sample Input:

4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20

Sample Output:

0 2 3 3 40


题目大意:

旅行者地图会给出沿高速公路在城市之间的距离以及每条高速公路的成本。现在,您应该编写一个程序来帮助旅行者确定他/她的出发城市和目的地之间的最短路径。如果这样的最短路径不是唯一的,则应该以最小的成本输出该路径,这保证是唯一的。

输入规格

每个输入文件包含一个测试用例。每种情况都从包含4个正整数N,M,S和D的行开始,其中N(≤500)是城市数(因此,城市从0到N-1编号); M是高速公路的数量; S和D分别是起始城市和目标城市。然后是M行,每行以以下格式提供公路信息:

City1 City2距离成本

其中所有数字均为不超过500的整数,并用空格分隔。

输出规格:

对于每个测试用例,在一行中打印沿起点到目的地的最短路径的城市,然后是路径的总距离和总成本。数字必须用空格隔开,并且输出末尾不得有多余的空格。

样本输入

4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20

样本输出:

0 2 3 3 40


思路:

dijkstra+优先队列优化


代码:

#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
struct node{
	int v;
	int len;
	node(int a,int b){v=a;len=b;}
	friend bool operator<(node a,node b){ //从小到大
		return a.len>b.len;
	}
};

const int maxn=550;    
const int inf = 1<<27; //到达不了
bool vis[maxn]={false}; //是否走过
int dis[maxn],sumcost[maxn]={0}; //距离,总花费
int cost[maxn][maxn];  //两点之间的花费(边权)
vector<node> g[maxn];  //邻接表存边
priority_queue<node> q;  //优先队列
int pre[maxn];   //记录前驱节点
vector<int> path;  //存路径

void dijk(int s) 
{
	fill(dis,dis+maxn,inf);
	dis[s] = 0;  
	sumcost[s] = 0;
	q.push(node(s,0)); //放入队列
	while(!q.empty())
	{
		int u=q.top().v;
		q.pop();
		if(vis[u]) continue;
		vis[u]=1;
		for(int i=0;i<g[u].size();i++)
		{
			int v=g[u][i].v;
			int len=g[u][i].len;
			if(vis[v]==false) 
			{
				if(dis[v] > dis[u]+len) //距离可优化
				{
					dis[v] = dis[u]+len;
					sumcost[v] = sumcost[u]+cost[u][v];
					pre[v] = u;
				}
				else if(dis[v]==dis[u]+len) //距离不可优化
				{
				   if(sumcost[v]>sumcost[u]+cost[u][v])//花费可优化
					{
						sumcost[v] = sumcost[u]+cost[u][v];
						pre[v] = u;
					}
					 
				}
				q.push(node(v,dis[v])); //入队
			}
		}
	}
} 


void dfs(int now)  //通过前驱节点找到这条路径
{
	if(pre[now]==-1) return; //该点为起点,结束
	path.push_back(pre[now]); 
	//放入vector(也可以直接输出,我这有点多此一举了)
	dfs(pre[now]); //搜索该点的前驱节点
}

int main() 
{
  int n,m,s,d;
  int a,b,len,money;
  cin>>n>>m>>s>>d;
  while(m--)
  {
  	 cin>>a>>b>>len>>money;
  	 g[a].push_back(node(b,len)); //无向图
  	 g[b].push_back(node(a,len));
  	 cost[a][b] = cost[b][a] = money;
  }
  pre[s]=-1;  //起点的前驱设为-1
  dijk(s);  
  
  path.push_back(d); //先把终点放入路径
  dfs(d); //走一遍dfs,找出路径
  for(int i=path.size()-1;i>=0;i--) //倒序输出
  	cout<<path[i]<<" ";

  cout<<dis[d]<<" "<<sumcost[d]; //输出距离 总花费
  return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章