1018 Public Bike Management (30 分)(圖的遍歷and最短路徑)
阿新 • • 發佈:2018-12-16
這題不能直接在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; }