1018 Public Bike Management (30 分)(图的遍历and最短路径)
这题不能直接在Dijkstra中写这个第一 标尺和第二标尺的要求 因为这是需要完整路径以后才能计算的 所以写完后可以在遍历
#include<bits/stdc++.h> using namespace std; int cmax,n,v,m; const int N=1e3; int weight[N]; int mp[N][N]; const int inf=0x3f3f3f3f; int dis[N]; int vis[N]; vector<int>path[N]; void Dijkstra() { fill(dis,dis+N,inf); fill(vis,vis+N,false); for(int i=0;i<=n;i++) dis[i]=mp[0][i]; dis[0]=0; for(int i=0;i<n;i++){ int u=-1; int minn=inf; for(int j=0;j<=n;j++){ if(!vis[j]&&minn>dis[j]){ minn=dis[j]; u=j; } } vis[u]=true; for(int j=0;j<=n;j++){ if(!vis[j]&&dis[j]>=mp[u][j]+dis[u]){ if(dis[j]>mp[u][j]+dis[u]){ dis[j]=mp[u][j]+dis[u]; path[j].clear(); path[j].push_back(u); } else if(dis[j]==mp[u][j]+dis[u]){ path[j].push_back(u); } } } } } vector<int>t,tt; int minNeed=inf; int minRemain=inf; void dfs(int v) { if(v==0){ t.push_back(v); int need=0;//需要从0点带的车数 int remain=0;//需要带回0点的车数 for(int i=t.size()-1;i>=0;i--){//必须倒着枚举 int id=t[i]; if(weight[id]>0){// >0 说明需要带走一部分自行车 remain+=weight[id]; } else{//需要补给 if(remain>abs(weight[id])){ remain-=abs(weight[id]); } else{ need+=abs(weight[id])-remain; remain=0; } } } if(need<minNeed){//第一标尺 minNeed=need; minRemain=remain; tt=t; } else if(need==minNeed&&remain<minRemain){//第二标尺 minRemain=remain; tt=t; } t.pop_back(); return; } t.push_back(v); for(int i=0;i<path[v].size();i++){ dfs(path[v][i]); } t.pop_back(); } int main() { scanf("%d %d %d %d",&cmax,&n,&v,&m); fill(weight,weight+N,0); for(int i=1;i<=n;i++){ int x; scanf("%d",&x); weight[i]=x-cmax/2; } fill(mp[0],mp[0]+N*N,inf); for(int i=0;i<m;i++){ int a,b,c; scanf("%d %d %d",&a,&b,&c); mp[a][b]=mp[b][a]=c; } Dijkstra(); dfs(v); printf("%d ",minNeed); for(int i=tt.size()-1;i>=0;i--){ if(i!=tt.size()-1) printf("->"); printf("%d",tt[i]); } printf(" %d\n",minRemain); return 0; }