codevs 1173 最优贸易(DP+SPFA运用)

/*
中国的题目 ——贱买贵卖 0.0
这题wa了好多遍
第一遍看着题 哎呀这不很简单嘛 从起点能到的点都是合法的点
然后统计合法的点里最大最小值 然后printf
也不知道哪里来的自信 就这么交了 然后爆零了
第二遍想了想 恩 刚开始思路有问题 必须先买后卖
买的点要在卖的前面 恩 很有道理
然后数组模拟着统计了一下i之前的最小值和i之后的最大值
并且确保每个点都是合法的
然后 连样例都不对了.....
第三遍 终于找到了问题的关键(好吧我是看到标签里有spfa才想到了)
因为他是图啊 图啊 而且是有向的 而且有双向边
这个嘛 当然还是跑一遍这个图 按照跑的顺序更新最大最小值
所以正反建边 正反分别跑最大最小就ok了
下面是wa的代码
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 500010
using namespace std;
int n,m,num,head[maxn],v[maxn],sm[maxn],bi[maxn];
bool f[maxn];
struct node
{
    int v,pre;
}e[maxn*2];
int init()
{
    int x=0;char s=getchar();
    while(s<‘0‘||s>‘9‘)s=getchar();
    while(s>=‘0‘&&s<=‘9‘){x=x*10+s-‘0‘;s=getchar();}
    return x;
}
void Add(int from,int to)
{
    num++;
    e[num].v=to;
    e[num].pre=head[from];
    head[from]=num;
}
void Dfs(int s)
{
    for(int i=head[s];i;i=e[i].pre)
      if(f[e[i].v]==0)
        {
          f[e[i].v]=1;
          Dfs(e[i].v);
        }
}
void Get_sb()
{
    sm[0]=maxn;
    for(int i=1;i<=n;i++)sm[i]=min(v[i],sm[i-1]);
    for(int i=n;i>=1;i--)bi[i]=max(v[i],bi[i-1]);
}
int main()
{
    n=init();m=init();
    for(int i=1;i<=n;i++)
      v[i]=init();
    int x,y,z;
    for(int i=1;i<=m;i++)
      {
          x=init();y=init();z=init();
          if(z==1)Add(x,y);
          else Add(x,y),Add(y,x);
      }
    f[1]=1;Dfs(1);
    Get_sb();
    int minn=0x3f3f3f3f,maxx=0;
    for(int i=1;i<=n;i++)
      if(f[i])
        {
          minn=min(minn,bi[i]-sm[i]);
          maxx=max(maxx,bi[i]-sm[i]);
        }
    printf("%d\n",maxx-minn);
    return 0;
}
/*这是Ac的代码*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 500010
using namespace std;
int n,m,num,num2,head[maxn],head2[maxn],v[maxn],dx[maxn],dy[maxn],ans;
bool f[maxn];
struct node
{
    int v,pre;
}e[maxn*2],e2[maxn*2];
int init()
{
    int x=0;char s=getchar();
    while(s<‘0‘||s>‘9‘)s=getchar();
    while(s>=‘0‘&&s<=‘9‘){x=x*10+s-‘0‘;s=getchar();}
    return x;
}
void Add(int from,int to)
{
    num++;
    e[num].v=to;
    e[num].pre=head[from];
    head[from]=num;
}
void Add2(int from,int to)
{
    num2++;
    e2[num2].v=to;
    e2[num2].pre=head2[from];
    head2[from]=num2;
}
void SPFA(int s)
{
    memset(dx,127/3,sizeof(dx));
    f[s]=1;dx[s]=v[s];
    queue<int>q;
    q.push(s);
    while(!q.empty())
      {
          int k=q.front();q.pop();
          for(int i=head[k];i;i=e[i].pre)
            {
                dx[e[i].v]=min(dx[e[i].v],min(v[e[i].v],dx[k]));
                if(f[e[i].v]==0)
                  {
                      f[e[i].v]=1;
                      q.push(e[i].v);
              }
          }
      }
}
void SPFA2(int s)
{
    f[s]=1;dy[s]=v[s];
    queue<int>q;
    q.push(s);
    while(!q.empty())
      {
          int k=q.front();q.pop();
          for(int i=head2[k];i;i=e2[i].pre)
            {
                dy[e2[i].v]=max(dy[e2[i].v],max(v[e2[i].v],dy[k]));
                if(f[e2[i].v]==0)
                  {
                      f[e2[i].v]=1;
                      q.push(e2[i].v);
              }
          }
      }
}
int main()
{
    n=init();m=init();
    for(int i=1;i<=n;i++)
      v[i]=init();
    int x,y,z;
    for(int i=1;i<=m;i++)
      {
          x=init();y=init();z=init();
          if(z==1)Add(x,y),Add2(y,x);
          else Add(x,y),Add(y,x),Add2(x,y),Add2(y,x);
      }
    SPFA(1);memset(f,0,sizeof(f));SPFA2(n);
    int minn=0x3f3f3f3f,maxx=0;
    for(int i=1;i<=n;i++)
      ans=max(ans,dy[i]-dx[i]);
    printf("%d\n",ans);
    return 0;
}
时间: 2024-12-17 11:59:22

codevs 1173 最优贸易(DP+SPFA运用)的相关文章

[CODEVS 1173] 最优贸易

描述 http://www.codevs.cn/problem/1173/ 分析 官方解法 先考虑如果题目中的线路不会构成环, 那么问题可以简化成一个DP就可以解决的问题=> 先正着DP, 找出在每个点之前可以买进的最低的价格 minp ; 再倒着DP, 统计出在每个点之后可以卖出的最高价格 maxp , 取所有点中的minp - maxp 的最大值就是最大的收益. 现在的问题就是解决环的存在, 因为有环的话没有一个拓扑序供我们DP使用. 所以用Tarjan算法求强联通分量缩点, 同时统计出缩点

P1073 最优贸易 建立分层图 + spfa

P1073 最优贸易:https://www.luogu.org/problemnew/show/P1073 题意: 有n个城市,每个城市对A商品有不同的定价,问从1号城市走到n号城市可以最多赚多少差价.(旅游为主,赚钱为辅,所以买入和卖出只进行一次. 思路: 建一个有三层的图,三层都是相同的普通的城市路线,第一层向第二层连从第i个城市买入商品的花费,第二层向第三层连从第i个城市卖出商品的所得.从1 向 第一层的终点 ,向第三层的终点跑一遍最大路就行了. #include <algorithm>

P1073 最优贸易

P1073 最优贸易 题目描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个 城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分 为双向通行的道路,双向通行的道路在统计条数时也计为 1 条. C 国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价 格不一定相同.但是,同一种商品在同一个城市的买入价和卖出价始终是相同的. 商人阿龙来到 C 国旅游.当他得知同一种商品在不同城市的价格可能会不同这一信息

NOIP2009 最优贸易

最优贸易 题目描述 Description C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双向通行的道路在统计条数时也计为 1 条. C 国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价格不一定相同.但是,同一种商品在同一个城市的买入价和卖出价始终是相同的. 商人阿龙来到 C 国旅游.当他得知同一种商品在不同城市的价格可能会不同这

vijos1754:最优贸易

开始的时候脑子抽风了又以为是floyed.分明和以前做过的一道题的方法类似好不好qwq.逆向存储+分两部分就ok了...spfa感觉真心强大. ---------------------------------------------------------------------------------------------------------------------- P1754最优贸易 Accepted 标签:NOIP提高组2009[显示标签] 描述 C 国有 n 个大城市和 m 条

最优贸易

最优贸易 (trade.pas/c/cpp) [问题描述] C 国有 n 个大城市和 m条道路,每条道路连接这 n 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双向通行的道路在统计条数时也计为 1 条. C国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价格不一定相同.但是,同一种商品在同一个城市的买入价和卖出价始终是相同的. 商人阿龙来到 C 国旅游.当他得知同一种商品在不同城市的价格

【图论】最优贸易

[NOIP2009]最优贸易 描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双向通行的道路在统计条数时也计为 1 条. C 国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价格不一定相同.但是,同一种商品在同一个城市的买入价和卖出价始终是相同的. 商人阿龙来到 C 国旅游.当他得知同一种商品在不同城市的价格可能会不同这一信息之

[NOIP2009提高组]最优贸易 tarjan题解

今天刚刚学会了用tarjan写缩点(以前用两遍dfs写的),此题调了我很久,需要考虑的情况有些多,但是做出来还是挺开心的. 首先通过tarjan缩点,之后要干的事情就是计算答案. 答案有两种情况,一是在一个联通块中买进卖出,二是在一个联通块中买入,但在另外一个联通块中卖出.但是需要注意的是,以上两种情况中的联通块需要满足起点可以到达它,它也可以到达终点,并且不在一个联通块中时,买进必在卖出前. 代码中的dp(x)记录的是从起点到现在买进价最低的,每次只要用当前最大价钱减去这个值,再去和ans做比

「CH6101」最优贸易

「CH6101」最优贸易 传送门 考虑一种贪心的思想:我们要尽量买价格小的货物,并尽量高价转卖. 我们记 : \(mn[i]\) 为从点 \(1\) 走到点 \(i\) 经过的价格最小的货物的价格. \(mx[i]\) 为从点 \(i\) 走到点 \(n\) 经过的价格最大的货物的价格. 这两个东西可以跑两次 \(\text{SPFA}\) 求得. 那么对于任何一个点,如果它位于最优解对应的路径上,那么该最优值一定不会小于 \(mx[i] - mn[i]\) 那么我们就可以把每个点 \(i\)