【一隻蒟蒻的刷題歷程】 【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;
}

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