PAT (Advanced Level) 1018 Public Bike Management

题解

  看完这题,直接来一套最短路。这次WA了,淦。

  因为这道题路径的选择条件为:第一标尺是距离短优先,第二标尺是从管理中心带出去的自行车少的优先,第三标尺是从站点带回去的自行车少的优先。

  只用最短路算法解决这道题的话,第二标尺和第三标尺不能被正确维护,因为最短路算法的特点,会出现改变其他站点的自行车数量,但是这个站点并不在你的最终路径上的情况。

  所以正确解法是先利用最短路算法将距离最短的路径(可能不止一条)保存下来,再利用深搜对这些在距离上最优的路径进行第二标尺和第三标尺的筛选,求得最优解。

错误代码

#include<bits/stdc++.h>
using namespace std;
struct node
{
    int to,w;
    node(int a,int b)
    {
        to=a;
        w=b;
    }
};
vector<node> edge[520];
int V,N,M,D,bike[520],dis[520],vis[520],path[520],cost[520];
void spfa();
void print(int p);
int main()
{
    int i,u,v,t;
    scanf("%d%d%d%d",&V,&N,&D,&M);
    V/=2;
    for(i=1;i<=N;i++) scanf("%d",&bike[i]);
    while(M--)
    {
        scanf("%d%d%d",&u,&v,&t);
        edge[u].push_back(node(v,t));
        edge[v].push_back(node(u,t));
    }
    spfa();
    printf("%d ",cost[D]>0?cost[D]:0);
    printf("0");print(D);
    printf(" %d",cost[D]<0?-cost[D]:0);
    system("pause");
    return 0;
}
void print(int p)
{
    if(path[p]==-1) return;
    print(path[p]);
    printf("->%d",p);
}
void spfa()
{
    fill(dis+1,dis+520,0x3fffffff);
    fill(path,path+520,-1);
    queue<int> que;
    int i,from,to,w;
    que.push(0);
    while(!que.empty())
    {
        from=que.front();
        que.pop();
        vis[from]=0;
        for(i=0;i<edge[from].size();i++)
        {
            to=edge[from][i].to;
            w=edge[from][i].w;
            if(dis[to]>dis[from]+w)
            {
                dis[to]=dis[from]+w;
                path[to]=from;
                cost[to]=cost[from]+V-bike[to];
                if(vis[to]==0)
                {
                    vis[to]=1;
                    que.push(to);
                }
            }
            else if(dis[to]==dis[from]+w)
            {
                if(abs(cost[to])>abs(cost[from]+V-bike[to]))
                {
                    cost[to]=cost[from]+V-bike[to];
                    path[to]=from;
                }
            }
        }
    }
}

正确代码

#include<bits/stdc++.h>
using namespace std;
struct node
{
   int to,w;
   node(int a,int b)
   {
      to=a;
      w=b;
   }
};
vector<node> edge[520];
vector<int> ans,temp,path[520];
int V,N,M,D,bike[520],dis[520],vis[520],mminneed=0x7fffffff,mminback=0x7fffffff;
void spfa();
void dfs(int p);
int main()
{
    int i,u,v,t;
    scanf("%d%d%d%d",&V,&N,&D,&M);
    for(i=1;i<=N;i++) scanf("%d",&bike[i]);
    while(M--)
    {
        scanf("%d%d%d",&u,&v,&t);
        edge[u].push_back(node(v,t));
        edge[v].push_back(node(u,t));
    }

    spfa();
    dfs(D);

    printf("%d ",mminneed);
    for(i=ans.size()-1;i>=0;i--)
    {
       if(i!=ans.size()-1) printf("->");
       printf("%d",ans[i]);
    }
    printf(" %d",mminback);
    
    system("pause");
    return 0;
}
void dfs(int p)
{
   int i;
   temp.push_back(p);
   if(p==0)
   {
      int need=0,back=0;
      for(i=temp.size()-2;i>=0;i--)
      {
         if(bike[temp[i]]>=V/2) back=back+bike[temp[i]]-V/2;
         else
         {
            if(back>=V/2-bike[temp[i]]) back=back-V/2+bike[temp[i]];
            else 
            {
               need=need+V/2-bike[temp[i]]-back;
               back=0;
            } 
         }
      }

      if(need<mminneed)
      {
         mminneed=need;
         mminback=back;
         ans=temp;
      }
      else if(need=mminneed&&back<mminback)
      {
         mminback=back;
         ans=temp;
      }
      
      temp.pop_back();
      return ;
   }

   for(i=0;i<path[p].size();i++)
      dfs(path[p][i]);
   
   temp.pop_back();
}
void spfa()
{
   fill(dis+1,dis+520,0x3fffffff);
   queue<int> que;
   int i,from,to,w;
   que.push(0);
   while(!que.empty())
   {
      from=que.front();
      que.pop();
      vis[from]=0;
      for(i=0;i<edge[from].size();i++)
      {
         to=edge[from][i].to;
         w=edge[from][i].w;
         if(dis[to]>dis[from]+w)
         {
            dis[to]=dis[from]+w;
            path[to].clear();
            path[to].push_back(from);
            if(vis[to]==0)
            {
               vis[to]=1;
               que.push(to);
            }
         }
         else if(dis[to]==dis[from]+w)
            path[to].push_back(from);
      }
   }
}