• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • YouClaw
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

yongchaoD

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

洛谷P1073 最优贸易 (分层图+spfa)

题意:多个节点,起点到终点,每个点可以买或卖水晶球,点与点之间有单向和双向之分,每个点水晶球的价格不一样(买卖价格相同)。问最多买卖一次,能赚取最高多少差价?(在赚不到差价的情况下他就无需进行贸易)。

思路:“这个'b'题,我不看题解我是想不出来,但是确实是个很好的题”。有两种做法,双向spfa和分层图,我就只说分层图做法(另一个也不会)。
分层图是多层,每层代表了不同的状态。这里有3层。

各层之间权值都=0,层与层之间权值不同,一层到二层是买入,所以权值是负,二层到三层是卖出,所以权值是正。
分层图就是存图麻烦,然后就是正常跑一个spfa(spfa是能处理负边的,具有伸缩,dij是不能的)就可以了。
题解注释的那一块是输出存的题,不懂了是如何存图的,可以输出看看,会是这样:

题解:

点击查看代码
//S 分层图
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+9;
int n,m,U,V,T,c;
vector<int>dis(N,-INT64_MAX),vis(N,0);//与dij的vis不同,此vis是判断节点i是否在队列中.
// 这里是spfa找到终点最大值,dis数组要初始化极小值。
vector<pair<int,int>>G[N];//first:点 second:权值

void spfa(){
    queue<int>q;
    q.push(1);
     dis[1]=0;
      while(!q.empty()){
          int u=q.front();
           q.pop();
            vis[u]=0;
             for(auto [x,y]:G[u]){//u-->x
                 if(dis[x]<dis[u]+y){//比较是否有更大值
                     dis[x]=dis[u]+y;
                      if(!vis[x]){
                          q.push(x),vis[x]=1;
                      }
                 }
             }
      }
}

signed main()
{
    scanf("%lld%lld",&n,&m);
    int n2=n*2;
    for(int i=1;i<=n;i++){//层与层之间只能单向图
        scanf("%lld",&c);
        G[i].push_back({n+i,-c});//一层
        G[n+i].push_back({n2+i,c});//二层
    }


    for(int i=1;i<=m;i++){
        scanf("%lld%lld%lld",&U,&V,&T);
        G[U].push_back({V,0});
        G[n+U].push_back({n+V,0});
        G[n2+U].push_back({n2+V,0});
        if(T==2){//双向图
            G[V].push_back({U,0});
            G[n+V].push_back({n+U,0});
            G[n2+V].push_back({n2+U,0});
        }
    }

//     for(int i=1;i<=3*n;i++){
//         cout<<i<<":";
//          for(auto x:G[i]){
//              cout<<x.first<<","<<x.second<<";";
//          }
//           cout<<endl;
//     }

      spfa();
      printf("%lld\n",dis[3*n]);
    return 0;
}

posted on 2024-07-10 12:09  yongchaoD  阅读(32)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3