题意:
输入四个正整数C,N,S,M(c<=100,n<=500),分别表示每个自行车站的最大容量,车站个数,此次行动的终点站以及接下来的M行输入即通路。接下来输入一行N个正整数表示每个自行车站初始拥有的自行车数量,接下来输入M行每行包含三个正整数分别表示一条双向边的端点以及这条路的长度。求去往终点车站一次所经历的最短路,多条最短路则优先少带出车辆,次优先少带回车辆。(路上经过站点时需要把该站点的车辆变为最大容量的一半)
代码:
#include<bits/stdc++.h>
using namespace std;
const int inf = 1e9;
int c,n,s,m;
int a[507];//每个站初始自行车数量
vector<pair<int,int> >adj[507];//邻接表
int d[507];//最短路距离
bool inq[507];//是否在队列中的标记
vector<int>pre[507];//前驱结点数组
vector<int>path,temp_path;
int sent=inf,take=inf;
void SPFA(){
queue<int>q;
for(int i=1;i<=n;++i)
d[i]=inf;
q.push(0);
inq[0]=true;
while(!q.empty()){
int u=q.front();
q.pop();
inq[u]=false;
for(int i=0;i<adj[u].size();++i){
int v=adj[u][i].first;
int val=adj[u][i].second;
if(!v)
continue;
if(d[u]+val<d[v]){
d[v]=d[u]+val;
pre[v].clear();
pre[v].push_back(u);
if(!inq[v]){
q.push(v);
inq[v]=true;
}
}
else if(d[u]+val==d[v])
pre[v].push_back(u);
}
}
}
void DFS(int x){
if(!x){
int remain=0,temp_sent=0;
temp_path.push_back(x);
for(int i=temp_path.size()-2;i>=0;--i){
int u=temp_path[i];
remain+=a[u]-c/2;
if(remain<0){
temp_sent-=remain;
remain=0;
}
}
if(temp_sent<sent){
path=temp_path;
sent=temp_sent;
take=remain;
}
else if(temp_sent==sent&&remain<take){
path=temp_path;
take=remain;
}
temp_path.pop_back();
}
temp_path.push_back(x);
for(int i=0;i<pre[x].size();++i)
DFS(pre[x][i]);
temp_path.pop_back();
}
int main(){
cin>>c>>n>>s>>m;
for(int i=1;i<=n;++i)
cin>>a[i];
int u,v,val;
for(int i=1;i<=m;++i){
cin>>u>>v>>val;
adj[u].push_back({v,val});
adj[v].push_back({u,val});
}
SPFA();
DFS(s);
cout<<sent<<" ";
for(int i=path.size()-1;i>=0;--i){
if(i<path.size()-1)
cout<<"->";
cout<<path[i];
}
cout<<" "<<take;
return 0;
}
【PAT甲级】1018 Public Bike Management (30 分)(SPFA,DFS)
原文:https://www.cnblogs.com/ldudxy/p/11338862.html