7-4 城市间紧急救援 (25 分)
作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。
输入格式:
输入第一行给出4个正整数、、、,其中()是城市的个数,顺便假设城市的编号为0 ~ ;是快速道路的条数;是出发地的城市编号;是目的地的城市编号。
第二行给出个正整数,其中第个数是第个城市的救援队的数目,数字间以空格分隔。随后的行中,每行给出一条快速道路的信息,分别是:城市1、城市2、快速道路的长度,中间用空格分开,数字均为整数且不超过500。输入保证救援可行且最优解唯一。
输出格式:
第一行输出最短路径的条数和能够召集的最多的救援队数量。第二行输出从到的路径中经过的城市编号。数字间以空格分隔,输出结尾不能有多余空格。
输入样例:
4 5 0 3 20 30 40 10 0 1 1 1 3 2 0 3 3 0 2 2 2 3 2
输出样例:
2 60 0 1 3
#include<bits/stdc++.h>
using namespace std;
const int inf= 0x3f3f3f3f;
vector<int>pre[600];
int tu[600][600];
int cost[999];
int n,m;
void dijkstra(int s)
{
int dist[999]= {0} ;
fill(dist,dist+600,inf);
dist[s] =0;
int book[700]= {0};
while(1)
{
int mmin = inf,o;
for(int i=0; i<n; i++)
{
if(!book[i]&&dist[i]<mmin)
{
mmin = dist[i];
o = i;
}
}
if(mmin==inf)break;
book[o] = 1;
for(int i=0; i<n; i++)
{
if(!book[i]&&dist[i]>dist[o]+tu[o][i])
{
dist[i] = dist[o]+tu[o][i];
pre[i].clear();
pre[i].push_back(o);
}
else if(!book[i]&&dist[i]==dist[o]+tu[o][i])
{
pre[i].push_back(o);
}
}
}
}
int cnt,Max = 0,d;
vector<int>ans;
vector<int>temp;
void dfs(int s,int e){
if(s==e){
temp.push_back(e);
int sum =0;
for(int aa:temp){
sum+=cost[aa];
ans = temp;
}
cnt++;
if(sum>Max){
Max = sum;
}
temp.pop_back();
return;
}
temp.push_back(s);
for(int u:pre[s]){
dfs(u,e);
}
temp.pop_back();
}
int main()
{
int s;
cin>>n>>m>>s>>d;
for(int i=0; i<=n; i++)
{
for(int j=0; j<=n; j++)
{
tu[i][j] = inf;
if(i==j)tu[i][j] = 0;
}
}
for(int i=0; i<n; i++)
cin>>cost[i];
int aa,bb,cc;
for(int i=0; i<m; i++)
{
cin>>aa>>bb>>cc;
tu[aa][bb] = cc;
tu[bb][aa] =cc;
}
dijkstra(s);
cnt =0 ;
dfs(d,s);
cout<<cnt<<" "<<Max<<endl;
int top = 1;
reverse(ans.begin(),ans.end());
for(int yy:ans)
{
if(top)top = 0;
else printf(" ");
cout<<yy;
}
}
`