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

P1073 最优贸易:https://www.luogu.org/problemnew/show/P1073

题意:

   有n个城市,每个城市对A商品有不同的定价,问从1号城市走到n号城市可以最多赚多少差价。(旅游为主,赚钱为辅,所以买入和卖出只进行一次。

思路:

  建一个有三层的图,三层都是相同的普通的城市路线,第一层向第二层连从第i个城市买入商品的花费,第二层向第三层连从第i个城市卖出商品的所得。从1 向 第一层的终点 ,向第三层的终点跑一遍最大路就行了。

  

#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>

using namespace std;
#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "\n";
#define pb push_back
#define pq priority_queue

typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 bll;
typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii;
typedef pair<int,pii> p3;

//priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
//#define endl ‘\n‘

#define OKC ios::sync_with_stdio(false);cin.tie(0)
#define FT(A,B,C) for(int A=B;A <= C;++A)  //用来压行
#define REP(i , j , k)  for(int i = j ; i <  k ; ++i)
#define max3(a,b,c) max(max(a,b), c);
#define min3(a,b,c) min(min(a,b), c);
//priority_queue<int ,vector<int>, greater<int> >que;

const ll oo = 1ll<<17;
const ll mos = 0x7FFFFFFF;  //2147483647
const ll nmos = 0x80000000;  //-2147483648
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f; //18
const int mod = 1000000007;
const double esp = 1e-8;
const double PI=acos(-1.0);
const double PHI=0.61803399;    //黄金分割点
const double tPHI=0.38196601;

template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<‘0‘||ch>‘9‘) f|=(ch==‘-‘),ch=getchar();
    while (ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
    return x=f?-x:x;
}
/*-----------------------showtime----------------------*/

            const int maxn = 1e5+9;

            vector<pii>mp[maxn*3];
            int a[maxn];
            int n,m;
            void addedge(int s,int t){
                mp[s].pb(pii(t, 0));
                mp[s + n].pb(pii(t + n,0));
                mp[s + 2 * n].pb(pii(t + 2 * n,0));

                mp[s].pb(pii(t + n, -a[s]));
                mp[s + n].pb(pii(t + 2 * n, a[s]));
            }

            int dis[maxn * 3];
            bool vis[maxn * 3];

            int spfa(int s,int t){

                memset(dis, -inf,sizeof(dis));
                dis[s] = 0;
                queue<int>que;  que.push(s);
                vis[s] = true;
                while(!que.empty()){
                    int u = que.front(); que.pop();
                    vis[u] = false;
                    for(int i=0; i<mp[u].size(); i++){
                        int v = mp[u][i].fi,w = mp[u][i].se;
                        if(dis[v] < dis[u] + w){
                            dis[v] = dis[u] + w;
                            if(vis[v] == false){
                                vis[v] = true;
                                que.push(v);
                            }
                        }
                    }
                }
                return dis[t];
            }
int main(){
            scanf("%d%d", &n, &m);
            int t = 3 * n + 1;
            for(int i=1; i<=n; i++) scanf("%d", &a[i]);
            for(int i=1; i<=m; i++){
                int u,v,c;
                scanf("%d%d%d", &u, &v, &c);
                if(c == 1) {
                    addedge(u,v);
                }
                else {
                    addedge(u,v);
                    addedge(v,u);
                }
            }

            // addedge(3*n, t);
            mp[3*n].pb(pii(t,0));
            mp[n].pb(pii(t, 0));
            printf("%d\n", spfa(1, t));
            return 0;
}

  

原文地址:https://www.cnblogs.com/ckxkexing/p/10351183.html

时间: 2024-11-02 01:21:27

P1073 最优贸易 建立分层图 + spfa的相关文章

P1073 最优贸易 (tarjan缩点+dp)

题目链接:https://www.luogu.com.cn/problem/P1073. C国有n n n个大城市和m mm 条道路,每条道路连接这 nnn个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 mmm 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双向通行的道路在统计条数时也计为 11 1条. CC C国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价格不一定相同.但是,同一种商品在同一个城市的买入价和卖出价始终是相同的. 商人阿

P1073 最优贸易

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

bzoj 1579: [Usaco2009 Feb]Revamping Trails 道路升级【分层图+spfa】

至死不用dijskstra系列2333,洛谷上T了一个点,开了O2才过 基本想法是建立分层图,就是建k+1层原图,然后相邻两层之间把原图的边在上一层的起点与下一层的终点连起来,边权为0,表示免了这条边的边权,然后答案就是第0层的s到k层的t的最短路,因为0权边总是从上一层连到下一层,所以到达k层就表示走了k条0权边 这样的点数是nk的,不管是dijskstra还是spfa都跑不过 然后仔细观察这张图的特性,发现不同层之间的更新只有上一层通过0权边更新下一层,所以考虑单层更新,每一层都做一次spf

luogu P1073 最优贸易

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

洛谷P1073 最优贸易==codevs1173 最优贸易

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

【luogu P1073 最优贸易】 题解

题目链接:https://www.luogu.org/problemnew/show/P1073 对于状态量相互影响的题目,分层图是个不错的想法. 考虑在题目中分为: 不交易: 直接从1到n出去,为0 交易: 先在某点买入,再从该点后所在路径上卖出. 买入卖出是两个操作,考虑可以分开在两张图上做,于是就有了分层图,共三张图. 我们把原图中的路径都设边权为0,表示在这条路上走对交易利润无影响,在第一张图上买入后,我们就走到下一张图,准备卖出操作. 设u->v 所以若从u点买入,到下一条边的v,即v

bzoj2763: [JLOI2011]飞行路线(分层图spfa)

2763: [JLOI2011]飞行路线 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3234  Solved: 1235[Submit][Status][Discuss] Description Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的价格.Alice和Bob现在要从一个城市沿着航线到达另一个城

BZOJ 3627 JLOI 2014 路径规划 分层图 SPFA+HEAP

题目大意:N个点M条无向边,每个点有可能有红绿灯,或者是加油站,或者单单是一个点.红绿灯太多会让人烦,太久不加油车子就会开不动,问最多通过K次红绿灯,从"start"点到"end"点的最少花费是多少. 思路:只能最多通过K次红绿灯,可以依据这个建分层图.f[ i ][ j ]为在已经通过i次红绿灯后,在j点时的最小花费.这只是总体的思路,具体是实现起来还是有其他一些小问题. 题目中有一个limit,表示从一个加油站到另一个加油站不能行驶超过这么远.仔细想想,其实那些

bzoj 2763: [JLOI2011]飞行路线【分层图+spfa】

为什么早年的题总是从0开始标号啊--又zz了一次WA 分层图的题只有这一个套路吧,建分层图,然后优化时间是分层跑spfa然后层与层之间单独跑即可 #include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; const int N=50005,inf=1e9; int n,m,k,s,t,h[N],cnt,dis[N],d[N]; bool