题目:作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。
输入:
输入第一行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0 ~ (N−1);M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号。
第二行给出N个正整数,其中第i个数是第i个城市的救援队的数目,数字间以空格分隔。随后的M行中,每行给出一条快速道路的信息,分别是:城市1、城市2、快速道路的长度,中间用空格分开,数字均为整数且不超过500。输入保证救援可行且最优解唯一。
输出:
第一行输出最短路径的条数和能够召集的最多的救援队数量。第二行输出从S到D的路径中经过的城市编号。数字间以空格分隔,输出结尾不能有多余空格。
分析:最短路问题,注意输出的是最短路条数(不是最优路径条数)
所以只要路径最短即可(单独记录)。
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
#define ll long long
const int inf = 0x3f3f3f3f;
const int N=1e5+50;
int pace[10000];//记录路径条数
int dis[1000];
int w[1000];
int mp[1000][1000];
int pre[1000];
int vis[1000];
int num[1000];//存储前面节点最大人数
int a[1000];
using namespace std;
int main()
{
int n,m,s,e;
cin>>n>>m>>s>>e;
for(int i=0;i<n;i++)
pace[i]=1;
memset(mp,inf,sizeof mp);
memset(w,0,sizeof 0);
memset(dis,inf,sizeof dis);
for(int i=0;i<n;i++)
{
cin>>w[i];
}
for(int i=0;i<m;i++)
{
int u,v,x,y;
cin>>u>>v>>x;
if(x<mp[u][v])
{
mp[u][v]=x;
mp[v][u]=x;
}
}
for(int i=0;i<n;i++)
{
if(mp[s][i]!=inf)
{
dis[i]=mp[s][i];
pre[i]=s;
num[i]=w[s];
}
}
dis[s]=0;
vis[s]=1;
pre[s]=-1;
//dijkstra
for(int i=0;i<n;i++)
{
int ans=inf,u;
for(int j=0;j<n;j++)
{
if(!vis[j]&&ans>dis[j])
{
ans=dis[j];
u=j;
}
}
vis[u]=1;
num[u]=num[pre[u]]+w[pre[u]];
for(int v=0;v<n;v++)
{
if(!vis[v]&&dis[v]>dis[u]+mp[u][v])
{
pace[v]=pace[u];
dis[v]=dis[u]+mp[u][v];
num[v]=num[u]+w[v];
pre[v]=u;
}
else if(!vis[v]&&dis[v]==dis[u]+mp[u][v])
{
pace[v]+=pace[u];
if(num[v]<num[u]+w[v])
{
num[v]=num[u]+w[v];
pre[v]=u;
}
}
}
}
int tot=0;
for(int i=e;i!=-1;i=pre[i])
{
a[tot++]=i;
}
printf("%d %d\n",pace[e],num[e]+w[e]);
for(int i=tot-1;i>=0;i--)
{
if(i==tot-1)
printf("%d",a[i]);
else
printf(" %d",a[i]);
}
return 0;
}