返回目录
题意
城市里有一些公共自行车站, 每个车站的自行车最大容量为一个偶数Cmax,且如果一个车站中自行车的数量恰好为Cmax/2,那么称该车站处于“完美状态”。而如果一个车站容量是满的或是空的,那么控制中心(PBMC)就会携带或从路上收集一定数量的自行车前往该车站,以使问题车站及沿途所有车站都达到“完美状态”。现在给出Cmax、车站数目N (不含控制中心PBMC)、问题车站编号Sp、无向边数M及边权,求一条从PBMC (记为0号)到达问题车站Sp的最短路径,输出需要从PBMC携带的自行车数目、最短路径、到达问题车站后需要带回的自行车数目。如果最短路径有多条,那么选择从PBMC携带的自行车数目最少的:如果仍然有多条,那么选择最后从问题车站带回的自行车数目最少的。注意:沿途所有车站的调整过程必须在前往问题车站的过程中就调整完毕,带回时不再调整。
样例(可复制)
10 3 3 5
6 7 0
0 1 1
0 2 1
0 3 3
1 3 1
2 3 1
//output
3 0->2->3 0
注意点
- 本题解题思路为Djikstra+DFS。具体为:先用Dijkstra找到最短路径,找的过程中,记录下每个路径的每个节点的前驱节点。使用DFS从问题站点出发,利用刚才记录下的前驱节点返回到PBMC,把路径记下,再从PBMC出发计算需要带的单车数量need和需要取回的单车数量remain,与minneed和minremain进行比较,更新最短路径。
#include<bits/stdc++.h>
using namespace std;
int Cmax,n,sp,m,minneed=INT_MAX,minremain=INT_MAX;//Cmax为最大容量,n为顶点数,sp为问题站点,m为边数
int G[510][510],weight[510],dis[510];//G为图,weight为车站单车数量,dis为到某节点的距离
bool vis[510]={false};//标记是否访问过该节点
vector<int> temp,path,pre[510];//temp为临时路径,path为最短路径,pre存储前驱节点
void Dijkstra(){
fill(dis,dis+n+1,INT_MAX); //注意第二个参数为dis+n+1
dis[0]=0;
while(!vis[sp]){
int v,minn=INT_MAX;
for(int i=0;i<=n;i++){
if(!vis[i]&&dis[i]<minn){
minn=dis[i];
v=i;
}
}
vis[v]=true;
for(int i=0;i<=n;i++){
if(!vis[i]&&G[v][i]!=0&&dis[i]>dis[v]+G[v][i]){
dis[i]=dis[v]+G[v][i];
pre[i].clear();
pre[i].push_back(v);
}else if(!vis[i]&&G[v][i]!=0&&dis[i]==dis[v]+G[v][i]){
pre[i].push_back(v);
}
}
}
}
void DFS(int v){
temp.push_back(v);
if(v==0){
int need=0,remain=0;
for(int i=temp.size()-1;i>=0;i--){//注意从后往前才是从PBMC出发到问题站点的路径
int now=temp[i];
if(weight[now]>=0){
remain+=weight[now];
}else{
if(remain>abs(weight[now])){
remain+=weight[now];
}else{
need+=abs(weight[now])-remain;
remain=0;
}
}
}
if(need<minneed){
path=temp;
minneed=need;
minremain=remain;
}else if(need==minneed&&remain<minremain){
path=temp;
minneed=need;
minremain=remain;
}
temp.pop_back();
return;
}
for(int i=0;i<pre[v].size();i++)DFS(pre[v][i]);
temp.pop_back();
}
int main(){
cin>>Cmax>>n>>sp>>m;
for(int i=1;i<=n;i++){
scanf("%d",&weight[i]);
weight[i]-=Cmax/2;
}
int u,v,w;
while(m--){
scanf("%d%d%d",&u,&v,&w);
G[u][v]=G[v][u]=w;
}
Dijkstra();
DFS(sp);
printf("%d ",minneed);
for(int i=path.size()-1;i>=0;i--){
printf("%d",path[i]);
if(i>0)printf("->");
}
printf(" %d",minremain);
return 0;
}