L2-001 緊急救援【最短路】

Enjoy_process發表於2019-03-25

                                                  L2-001 緊急救援

                       https://pintia.cn/problem-sets/994805046380707840/problems/994805073643683840

 

 

題意

作為一個城市的應急救援隊伍的負責人,你有一張特殊的全國地圖。在地圖上顯示有多個分散的城市和一些連線城市的快速道路。每個城市的救援隊數量和每一條連線兩個城市的快速道路長度都標在地圖上。當其他城市有緊急求助電話給你的時候,你的任務是帶領你的救援隊儘快趕往事發地,同時,一路上召集儘可能多的救援隊。

輸入

輸入第一行給出4個正整數N、M、S、D,其中N(2≤N≤500)是城市的個數,順便假設城市的編號為0 ~ (N−1);M是快速道路的條數;S是出發地的城市編號;D是目的地的城市編號。第二行給出N個正整數,其中第i個數是第i個城市的救援隊的數目,數字間以空格分隔。隨後的M行中,每行給出一條快速道路的資訊,分別是:城市1、城市2、快速道路的長度,中間用空格分開,數字均為整數且不超過500。輸入保證救援可行且最優解唯一。

輸出

第一行輸出最短路徑的條數和能夠召集的最多的救援隊數量。第二行輸出從S到D的路徑中經過的城市編號。數字間以空格分隔,輸出結尾不能有多餘空格。

樣例輸入

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

樣例輸出

2 60
0 1 3

分析

最短路問題,使用Dijkstra演算法,求最短路,當最短路不唯一時,選擇所經過城市的救援人數總數最多的一條。road[i]=j表示到達城市 i 的最短路徑有 j 條數,具體看程式它是如何計算的(也可改用dfs求解最短路的條數)。

C++程式

#include<iostream>
#include<vector>
#include<queue>

using namespace std;

const int N=505;
const int INF=0x3f3f3f3f;

//邊 
struct Edge{
	int v,cost;
	Edge(int v,int cost):v(v),cost(cost){}
};

//結點 
struct Node{
	int u,cost;
	Node(){}
	Node(int u,int cost):u(u),cost(cost){}
	bool operator <(const Node &q)const//使用優先佇列,因此要過載<運算子 
	{
		return cost>q.cost;
	}
};

vector<Edge>g[N];//圖的鄰接矩陣 
bool vis[N]; 
int n,path[N],dist[N],tmp_num[N],num[N],road[N];//road[i]表示到達結點i的路徑數 

//列印路徑 
bool flag=false;

void print(int e)
{
	if(path[e]!=-1) print(path[e]);
	if(flag) printf(" ");
	flag=true;
	printf("%d",e);
}

//最短路演算法 
void dijkstra(int s,int e)
{
	for(int i=0;i<n;i++)//初始化 
	{
		vis[i]=false;
		road[i]=0;
		path[i]=-1;
		dist[i]=INF;
		tmp_num[i]=0;
	}
	priority_queue<Node>q;
	q.push(Node(s,0));
	dist[s]=0,tmp_num[s]=num[s];
	road[s]=1;//初始化到達城市s的最短路條數為1 
	while(!q.empty())
	{
		Node f=q.top();
		q.pop();
		int u=f.u;
		if(!vis[u])
		{
			vis[u]=true;
			for(int i=0;i<g[u].size();i++)
			{
				int v=g[u][i].v;
				int len=dist[u]+g[u][i].cost;
				int cnt=tmp_num[u]+num[v];
				if(len<dist[v]) 
					road[v]=road[u];//此時從u走到v,v的最短路條數和u一樣 
				else if(len==dist[v])
					road[v]+=road[u];//此時可以選擇從u走到v,v的最短路條數要加上這額外的 
				if(len<dist[v]||(len==dist[v]&&cnt>tmp_num[v]))//滿足條件就進行更新 
				{
					path[v]=u;
					dist[v]=len;
					tmp_num[v]=cnt;
					q.push(Node(v,dist[v]));
				}
			}
		}
	}
	printf("%d %d\n",road[e],tmp_num[e]); 
	print(e);
	printf("\n");
}

int main()
{
	int m,s,d;
	scanf("%d%d%d%d",&n,&m,&s,&d);
	for(int i=0;i<n;i++)
	  scanf("%d",&num[i]);
	for(int i=1;i<=m;i++)
	{
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		g[a].push_back(Edge(b,c));
		g[b].push_back(Edge(a,c));
	}
	dijkstra(s,d);
	return 0;
}

 

 

相關文章