【NOIP2009提高组T3】最优贸易-双向SPFA

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

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

以下是本人代码:

#include 
#include 
#include 
#include 
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]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; 
}


你可能感兴趣的:(图论-最短路)