题目
As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some other city, your job is to lead your men to the place as quickly as possible, and at the mean time, call up as many hands on the way as possible.
Input Specification:
Each input file contains one test case. For each test case, the first line contains 4 positive integers: N (≤500) - the number of cities (and the cities are numbered from 0 to N−1), M - the number of roads, C1 and C2 - the cities that you are currently in and that you must save, respectively. The next line contains N integers, where the i-th integer is the number of rescue teams in the i-th city. Then M lines follow, each describes a road with three integers c1, c2 and L, which are the pair of cities connected by a road and the length of that road, respectively. It is guaranteed that there exists at least one path from C1 to C2.
Output Specification:
For each test case you should output the sum of A and B in one line, with the same format as the input. Notice that there must be NO extra space at the end of each line. Please be accurate to 1 decimal place.
Sample Input:
5 6 0 2
1 2 1 5 3
0 1 1
0 2 2
0 3 1
1 2 1
2 4 1
3 4 1
Sample Output:
2 4
限制:
代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB
题目大意
无向图中,给出每个点的点权、每个边的边权(即两点之间距离),使起点到终点距离最短。求最短路径数及最大点权之和。
输入
第一行有四个正整数:N(<= 500)是城市的个数(城市的编号从0到N-1),M是道路的个数,C1和C2分别是起点和终点。下一行有N个整数,第i个整数是第i个城市中救援队的数量。下面M行道路。每一行有三个整数c1,c2和L,分别表示道路连接的两个城市以及道路的长度。
输出
一行中输出两个数字:C1和C2之间不同的最短路径的个数及最多的救援队数量。一行中的所有数字必须被一个空格分隔开,在每行的结尾不允许出现空格。
思路
此题为单源最短路径求解问题,采用Dijkstra算法。具体可参考博客:
算法之迪杰斯特拉(dijkstra)非常详细介绍_PRML_MAN的博客-CSDN博客_迪杰斯特拉
以下是代码段(5ms)
#include<iostream>
#include<algorithm>
using namespace std;
const int INF = 1000000000;//设置大数表示无穷大
const int maxn = 510;
int n,e,s,d;//n为城市数量,e为道路数量,s为起点,d为终点
int el[maxn][maxn];//存储边权
int v[maxn];//是否被访问过
int noh[maxn];//存储点权
int pathl[maxn];//起点到所有点的最短路径边权
int pathc[maxn];//起点到其他点的最短路径数目
int maxh[maxn];//起点到其他点的全部最短路径中的点权最大值
void Dijkstra();//算法函数
int main()
{
cin>>n>>e>>s>>d;
for(int i=0;i<n;i++)
cin>>noh[i];
for(int i=0;i<e;i++)
{
int in1,in2,in3;
cin>>in1>>in2>>in3;
el[in1][in2]=el[in2][in1]=in3;//无向图
}
Dijkstra();
cout<<pathc[d]<<" "<<maxh[d]<<endl;
return 0;
}
void Dijkstra()
{
fill(pathl,pathl+maxn,INF);//初始化
pathl[s]=0;
pathc[s]=1;
maxh[s]=noh[s];
while(1)//不断更新起点到其他点的最短路径,并更新最短路径的点权
{
/*找出本轮尚未确定最短路径的城市中,起点到剩余城市中,距离最小minl的那个城市mini。
如果minl是无穷大,证明起点城市与剩余城市均不可达,即不连通;
如果mini就是目标城市d,则表明已经确定起点城市到目标城市的最短路径,提前结束寻找。
否则,将本轮能确定最短路径的城市mini设为已经处理好,v[mini]=1;*/
int minl=INF,mini=-1;
for(int i=0;i<n;i++)
{
if(v[i]==1)continue;
if(pathl[i]<minl)
{
minl=pathl[i];
mini=i;
}
}
if(minl==INF||mini==d)break;
v[mini]=1;
//起点城市——城市mini——其他城市i,路径更短则更新
for(int i=0;i<n;i++)
{
//如果城市i已经处理好,或者城市mini到不了城市i,则跳过
if(v[i]==1||el[mini][i]==0)continue;
int templ=pathl[mini]+el[mini][i];
int temph=maxh[mini]+noh[i];
if(templ<pathl[i])
{
pathl[i]=templ;
maxh[i]=temph;
pathc[i]=pathc[mini];
}
else if(templ==pathl[i])
{
pathc[i]+=pathc[mini];
if(temph>maxh[i])
maxh[i]=temph;
}
}
}
}