1. 题目地址:http://www.patest.cn/contests/pat-a-practise/1003
2.分析:
本题要求输出特定俩点间最短路径的条数和最短路径中能call up的最多救援队数。
由特定俩点间的最短路径易想到dijkstra算法,但原始的dijkstra算法只能求出特定俩点间的最短距离,无法求出最短路径的条数等其它信息。这里我们应用了dijkstra算法的思想,但在计算的过程中我们记录路径距离相应的条数及相应的最多救援队数。
3. 代码:
#include <stdio.h>
using namespace std;
int main()
{
//从文本输入数据:
//#ifndef ONLINE_JUDGE
// freopen("in.txt","r",stdin);
//#endif
int n,m,s,d;//城市数,路径数,原点,目的点
int teams[500];//救援队
int G[500][500];//图
struct E
{
int dis;//距原点的距离
int num;//原点到该点为此距离的条数
int maxTeams;//该距离下原点可call up至此点的最大救援队数
};
struct E edge[500];//与原点间的距离等相应的信息
scanf("%d%d%d%d",&n,&m,&s,&d);
for(int i=0;i<n;++i){
int iTmp;
scanf("%d",&iTmp);
teams[i] = iTmp;
}
//初始化图信息
for(int j=0;j<n;++j){
for(int k = 0;k<n;++k){
G[j][k]= -1;//距离为无穷远
}
G[j][j]=0;
}
int c1,c2,L;
for(int i=0;i<m;++i){
scanf("%d%d%d",&c1,&c2,&L);
G[c1][c2]=L;
G[c2][c1]=L;
}
for(int i=0;i<n;++i){
edge[i].dis=-1;
edge[i].num=0;
edge[i].maxTeams=0;
}
bool mark[500]={0};//点是否被选取,初始化为未被选取
int newP=s;
edge[s].dis = 0;
edge[s].num = 1;
edge[s].maxTeams = teams[s];
mark[newP]=true;//点newP已被选
int num = n-1;//依次选取距离最小的n-1个点
int newDis;
while(num--){
for(int j=0;j<n;++j){//更新与newP点相连的点的edge信息
if(mark[j])
continue;
if(G[newP][j] == -1)
continue;
newDis = edge[newP].dis + G[newP][j];
if(edge[j].dis == newDis){//发现距离相同的路径
edge[j].num += edge[newP].num;//路径数相加
if((edge[newP].maxTeams + teams[j]) > edge[j].maxTeams)//最大救援队数为距离相同的路径中救援队数较大的
edge[j].maxTeams = edge[newP].maxTeams + teams[j];
}else if(edge[j].dis == -1 || edge[j].dis > newDis){//发现更小的距离,进行更新
edge[j].dis = newDis;
edge[j].num = edge[newP].num;
edge[j].maxTeams = edge[newP].maxTeams + teams[j];
}
}
int min = 123123123;
for(int k = 0;k<n;++k){//选取距离最小的点
if(mark[k])
continue;
if(edge[k].dis == -1)
continue;
if(edge[k].dis < min){
min = edge[k].dis;
newP = k;
}
}
mark[newP] = true;
if(newP == d)//到目的点的距离等相应的信息已找到,则结束
break;
}
printf("%d %d\n",edge[d].num,edge[d].maxTeams);
return 0;
//关闭输入文本
//#ifndef ONLINE_JUDGE
// fclose(stdin);
//#endif
}
时间复杂度:O(n^2)