1. 程式人生 > >1018 Public Bike Management (30 分)(圖的遍歷and最短路徑)

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; }