zoukankan      html  css  js  c++  java
  • 【NOIP2009提高组T3】最优贸易-双向SPFA

    题目大意:有N个城市,它们之间有M条道路相连,可能是单向道路或双向道路。对于同一种商品,在每个城市的价格不一定相同,一个商人在1号城市出发,要走到n号城市,他想在路径中某一个城市买入,并在之后的某一个城市卖出以赚取差价(差价等于卖出的城市中的价格减去买入的城市中的价格),求出这个商人可以赚到的最大差价。

    做法:在存储图的同时存储一个与这个图相反的图(单向路径的指向相反,双向路径不受影响),对反图做一次SPFA,求出从每个点出发到终点的路径上的最大卖价sell[i](在反图中表现为终点到每个点的路径上的最大的点权),再对正图做一次SPFA,求出从起点到每个点的路径上的最小买价buy[i],最后枚举每个点,求出最大差价(sell[i]-buy[i])即可。由于点很多,边相对来说很少,所以我们使用邻接表来存储。

    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    long n,m,price[100010]={0},last[100010]={0},qlast[100010]={0},total,qtotal;
    long buy[100010],sell[100010],v[100010]={0};
    
    struct
    {
      long p,next;
    }form[1100010],qform[1100010];
    
    void spfa()
    {
      long q[500010]={0},h,t;
      h=1;
      t=2;
      q[h]=1;
      v[q[h]]=1;
      for(int i=1;i<=n;i++) buy[i]=999999999;
      while(h!=t)
      {
        v[q[h]]=0;
        for(int i=q[h];i!=0;i=form[i].next)
          if (price[form[q[h]].p]<buy[form[i].p])
          {
            buy[form[i].p]=price[form[q[h]].p];
            if (!v[form[i].p]) {v[form[i].p]=1;q[t]=form[i].p;t++;if (t>500001) t=1;}
          }
        h++;if (h>500001) h=1;
      }
    }
    
    void qspfa()
    {
      long q[500010]={0},h,t;
      h=1;
      t=2;
      q[h]=n;
      v[q[h]]=1;
      for(int i=1;i<=n;i++) sell[i]=0;
      while(h!=t)
      {
        v[q[h]]=0;
        for(int i=q[h];i!=0;i=qform[i].next)
          if (price[qform[q[h]].p]>sell[qform[i].p])
          {
            sell[qform[i].p]=price[qform[q[h]].p];
            if (!v[qform[i].p]) {v[qform[i].p]=1;q[t]=qform[i].p;t++;if (t>500001) t=1;}
          }
        h++;if (h>500001) h=1;
      }
    }
    
    void input()
    {
      cin >> n >> m;
      total=qtotal=n;
      for(int i=1;i<=n;i++)
      {
        cin >> price[i];
        last[i]=i;
        qlast[i]=i;
        form[i].p=i;
        qform[i].p=i;
      }
      for(int i=1;i<=m*2+n;i++)
      {
        form[i].next=0;
        qform[i].next=0;
      }
      for(int i=1;i<=m;i++)
      {
        int x,y,z;
        cin >> x >> y >> z;
        total++;qtotal++;
        form[last[x]].next=total;
        form[total].p=y;
        last[x]=total;
        qform[qlast[y]].next=qtotal;
        qform[qtotal].p=x;
        qlast[y]=qtotal;
        if (z==2)
        {
          total++;qtotal++;
          form[last[y]].next=total;
          form[total].p=x;
          last[y]=total;
          qform[qlast[x]].next=qtotal;
          qform[qtotal].p=y;
          qlast[x]=qtotal;
        }
      }
    }
    
    void output()
    {
      long ans=0;
      for(int i=1;i<=n;i++)
        if (sell[i]-buy[i]>ans) ans=sell[i]-buy[i];
      cout << ans;
    }
    
    int main()
    {
      input();
      spfa();
      qspfa();
      output();
      
      return 0; 
    }
    


  • 相关阅读:
    数据库(2019年10月30日)
    (面试题)反射(2019年10月28日)
    反射(2019年10月28日)
    常微分复习重点
    重要定理及其证明
    实变函数复习重点
    泛函分析重点定理
    自旋玻璃简介
    Fnight博文发布规范
    [分析力学]解题思路
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793938.html
Copyright © 2011-2022 走看看