PAT甲级1003
题目大意:给出n座城市,m条边,开始的城市start以及目标城市end,第二行给出每座城市的救援队数量,接下来m行,每行给出一条边以及这条边的长度,求从start到end的最短路径条数,以及这些路径当中所能聚集到的最大救援队数量
主要用Dijkstra算法,开辟dis数组存放从start到每座城市的最短路径,rescue记录初始每座城市的救援队数量,maxrescue记录最短路径当中最大的救援队数量,num记录最短路径的条数,road记录每条路。这里要注意下num最短路径条数的处理,不是简单的重置1或者0,也不是自加加,要根据中介点u来判断当前路径条数的变化。例如处理j城时,如果通过中介u使得最短路径变小了则到j的最短路径就是u的最短路径条数;如果通过中介u变大了不做任何处理;如果相等则j的最短路径条数要再加上u的条数。
#include <iostream>
#include <vector>
#include <algorithm>
#define INF 100000000
#define MAXN 501
using namespace std;
int n,m;
int road[MAXN][MAXN];
int dis[MAXN],rescue[MAXN],maxrescue[MAXN],num[MAXN];
bool visit[MAXN]={false};
void init(){
for(int i=0;i<n;i++){
fill(road[i],road[i]+n,INF);
}
fill(visit,visit+n,false);
fill(dis,dis+n,INF);
}
void Dijkstra(int start){
dis[start]=0;
num[start]=1;
maxrescue[start]=rescue[start];
for(int i=0;i<n;i++){
int u=-1,min=INF;
for(int j=0;j<n;j++){
if(!visit[j]&&dis[j]<min){
u=j;
min=dis[j];
}
}
if(u==-1) return ;
visit[u]=true;
for(int j=0;j<n;j++){
if(!visit[j]&&road[u][j]<INF&&road[u][j]+dis[u]<=dis[j]){ //路径更新
if(road[u][j]+dis[u]==dis[j]){ //最短路径相同时比较救援队数量
num[j]+=num[u]; //若通过中介点找到的最短路径和不经过中介最短路径长度相同则到j最短路径条数加上u的最短路径条数
if(maxrescue[u]+rescue[j]>maxrescue[j]) maxrescue[j]=maxrescue[u]+rescue[j];
}
else{ //最短路径更短时更新路径
num[j]=num[u]; //若通过中介点找到的最短路径和不经过中介最短路径长度不同且更短则到j最短路径条数就是u的最短路径条数
dis[j]=road[u][j]+dis[u];
maxrescue[j]=maxrescue[u]+rescue[j];
}
}
}
}
}
int main(){
int start,end,tmp,city1,city2,length;
scanf("%d%d%d%d",&n,&m,&start,&end);
init();
for(int i=0;i<n;i++){
scanf("%d",&tmp);
rescue[i]=tmp;
}
for(int i=0;i<m;i++){
scanf("%d%d%d",&city1,&city2,&length);
road[city1][city2]=road[city2][city1]=length;
}
Dijkstra(start);
printf("%d %d",num[end],maxrescue[end]);
system("pause");
return 0;
}