返回目录
题意
给出N个城市,M条无向边。每个城市中都有一定数目
的救援小组,所有边的边权已知。现在给出起点和终点,求从起点到终点的最短路径条数及最短路径上的救援小组数目之和。如果有多条最短路径,则输出数目之和最大的。
样例(可复制)
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
//output
2 4
注意点
- 对dis进行初始化的时候不能使用memset
- 本题没有起点与终点不连通的测试点
- Dijkstra的思想为:一直找当前连通块能去的最短距离的点,将该点加入连通块
#include <bits/stdc++.h>
using namespace std;
int n,m,st,ed;//n个城市,m条边,起点,终点
int city[510],dis[510],num[510],team[510];//存放每个城市的救援队数量,最短距离 ,标记访问过的城市
bool vis[510]={false};
int G[510][510];//图
void Dijkstra(){
fill(dis,dis+n,INT_MAX);
dis[st]=0;
num[st]=1;
team[st]=city[st];
while(!vis[ed]){
int MIN=INT_MAX,v;//找出目前距离最短的还没有被访问的城市
for(int i=0;i<n;++i)
if(!vis[i]&&MIN>dis[i]){
MIN=dis[i];
v=i;
}
vis[v]=true;//标记
for(int i=0;i<n;++i)
if(!vis[i]&&G[v][i]!=0&&dis[v]+G[v][i]<dis[i]){
dis[i]=dis[v]+G[v][i];//更新最短路径长度
num[i]=num[v];//更新最短路径数量
team[i]=team[v]+city[i];//更新城市的救护队数量
}else if(G[v][i]!=0&&dis[v]+G[v][i]==dis[i]){
num[i]+=num[v];//增加最短路径数量
team[i]=max(team[i],team[v]+city[i]);//找出能够召集最多的城市救护队数量
}
}
}
int main(){
cin>>n>>m>>st>>ed;
for(int i=0;i<n;i++)scanf("%d",&city[i]);
int a,b,c;
while(m--){
scanf("%d%d%d",&a,&b,&c);
G[b][a]=G[a][b]=c;
}
Dijkstra();
cout<<num[ed]<<" "<<team[ed]<<endl;
return 0;
}