zoukankan      html  css  js  c++  java
  • 洛谷 P1073 最优贸易

    题目描述

    C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市。任意两个

    城市之间最多只有一条道路直接相连。这 m 条道路中有一部分为单向通行的道路,一部分

    为双向通行的道路,双向通行的道路在统计条数时也计为 1 条。

    C 国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价

    格不一定相同。但是,同一种商品在同一个城市的买入价和卖出价始终是相同的。

    商人阿龙来到 C 国旅游。当他得知同一种商品在不同城市的价格可能会不同这一信息

    之后,便决定在旅游的同时,利用商品在不同城市中的差价赚回一点旅费。设 C 国 n 个城

    市的标号从 1~ n,阿龙决定从 1 号城市出发,并最终在 n 号城市结束自己的旅行。在旅游的

    过程中,任何城市可以重复经过多次,但不要求经过所有 n 个城市。阿龙通过这样的贸易方

    式赚取旅费:他会选择一个经过的城市买入他最喜欢的商品――水晶球,并在之后经过的另

    一个城市卖出这个水晶球,用赚取的差价当做旅费。由于阿龙主要是来 C 国旅游,他决定

    这个贸易只进行最多一次,当然,在赚不到差价的情况下他就无需进行贸易。

    假设 C 国有 5 个大城市,城市的编号和道路连接情况如下图,单向箭头表示这条道路

    为单向通行,双向箭头表示这条道路为双向通行。

    假设 1~n 号城市的水晶球价格分别为 4,3,5,6,1。

    阿龙可以选择如下一条线路:1->2->3->5,并在 2 号城市以 3 的价格买入水晶球,在 3

    号城市以 5 的价格卖出水晶球,赚取的旅费数为 2。

    阿龙也可以选择如下一条线路 1->4->5->4->5,并在第 1 次到达 5 号城市时以 1 的价格

    买入水晶球,在第 2 次到达 4 号城市时以 6 的价格卖出水晶球,赚取的旅费数为 5。

    现在给出 n 个城市的水晶球价格,m 条道路的信息(每条道路所连接的两个城市的编号

    以及该条道路的通行情况)。请你告诉阿龙,他最多能赚取多少旅费。

    输入输出格式

    输入格式:

    第一行包含 2 个正整数 n 和 m,中间用一个空格隔开,分别表示城市的数目和道路的

    数目。

    第二行 n 个正整数,每两个整数之间用一个空格隔开,按标号顺序分别表示这 n 个城

    市的商品价格。

    接下来 m 行,每行有 3 个正整数,x,y,z,每两个整数之间用一个空格隔开。如果 z=1,

    表示这条道路是城市 x 到城市 y 之间的单向道路;如果 z=2,表示这条道路为城市 x 和城市

    y 之间的双向道路。

    输出格式:

    输出文件 trade.out 共 1 行,包含 1 个整数,表示最多能赚取的旅费。如果没有进行贸易,

    则输出 0。

    输入输出样例

    输入样例#1:
    5 5 
    4 3 5 6 1 
    1 2 1 
    1 4 1 
    2 3 2 
    3 5 1 
    4 5 2 
    输出样例#1:
    5

    说明

    【数据范围】

    输入数据保证 1 号城市可以到达 n 号城市。

    对于 10%的数据,1≤n≤6。

    对于 30%的数据,1≤n≤100。

    对于 50%的数据,不存在一条旅游路线,可以从一个城市出发,再回到这个城市。

    对于 100%的数据,1≤n≤100000,1≤m≤500000,1≤x,y≤n,1≤z≤2,1≤各城市

    水晶球价格≤100。

    NOIP 2009 提高组 第三题0

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio> 
     4 #include<vector>
     5 #include<queue>
     6 #define maxn 100000+5
     7 using namespace std;
     8 struct Edges{
     9     int from,to,next;
    10 }e[maxn*10];
    11 int n,m,dis[maxn],ru[maxn],chu[maxn],head[maxn],tot;
    12 bool vis[maxn];
    13 inline void addedge(int u,int v){
    14     /*Edges e;e.from=u;e.to=v;
    15     edge.push_back(e);int m=edge.size();
    16     G[u].push_back(m-1);*/
    17     e[++tot].from=u;e[tot].to=v;
    18     e[tot].next=head[u];head[u]=tot;
    19 }
    20 int spfa(int U,int V){
    21     for(int i=1;i<=n;i++)dis[i]=-maxn;
    22     dis[U]=0;vis[U]=1;queue<int>q;
    23     q.push(U);
    24     int u;
    25     while(!q.empty()){
    26         u=q.front();q.pop();vis[u]=0;
    27         for(int i=head[u];i;i=e[i].next){
    28             bool mark=0;
    29             if(dis[e[i].to]<chu[e[i].to]-ru[e[i].from]){
    30                 dis[e[i].to]=chu[e[i].to]-ru[e[i].from];
    31                 ru[e[i].to]=min(ru[e[i].to],ru[e[i].from]);
    32                 mark=1;
    33             }
    34             if(dis[e[i].to]<dis[e[i].from]){
    35                 dis[e[i].to]=dis[e[i].from];
    36                 ru[e[i].to]=min(ru[e[i].to],ru[e[i].from]);
    37                 mark=1;
    38             }
    39             if(mark)
    40               if(!vis[e[i].to]) q.push(e[i].to);
    41         }
    42     }
    43     if(dis[V]>0)
    44         return dis[V];
    45     return 0;
    46 }
    47 int main(){
    48     scanf("%d%d",&n,&m);
    49     for(int i=1;i<=n;i++){
    50         scanf("%d",&ru[i]);
    51         chu[i]=ru[i];
    52     }
    53     for(int i=1,x,y,z;i<=m;i++){
    54         scanf("%d%d%d",&x,&y,&z);
    55         addedge(x,y);
    56         if(z==2) addedge(y,x);
    57     }
    58     printf("%d",spfa(1,n));
    59 }

    莫名的RE-_- -_-

     我的思路是ru维护到当前点始最低买入价格、chu维护到当前点时最高卖出价格

    来自神犇的AC代码:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<queue>
      6 using namespace std;
      7 const int maxn = 100010;
      8 const int maxe = 500050;
      9 int n,m,tot1,tot2,dis[maxn];
     10 int fst1[maxn],fst2[maxn],minn[maxn],maxx[maxn];
     11 bool vis1[maxn],vis2[maxn];
     12 struct edge{
     13     int to,next;
     14 }es1[maxe],es2[maxe];
     15 
     16 void build1(int ff,int tt)
     17 {
     18     es1[tot1].to = tt;
     19     es1[tot1].next = fst1[ff];
     20     fst1[ff] = tot1++;
     21 }
     22 
     23 void build2(int ff,int tt)
     24 {
     25     es2[tot2].to = tt;
     26     es2[tot2].next = fst2[ff];
     27     fst2[ff] = tot2 ++;
     28 }
     29 
     30 void spfa1()
     31 {
     32     queue<int>q;
     33     q.push(1);
     34     vis1[1] = 1;
     35     minn[1] = dis[1];
     36     while(!q.empty())
     37     {
     38         int u = q.front();
     39         q.pop();
     40         for(int i = fst1[u];i;i = es1[i].next)
     41         {
     42             int v = es1[i].to;
     43             minn[v] = min(minn[u],dis[v]);
     44             if(!vis1[v])
     45             {
     46                 q.push(v);
     47                 vis1[v] = 1;
     48             }
     49         }
     50     }
     51 }
     52 void spfa2()
     53 {
     54     queue<int>q;
     55     q.push(n);
     56     vis2[n] = 1;
     57     maxx[n] = dis[n];
     58     while(!q.empty())
     59     {
     60         int u = q.front();
     61         q.pop();
     62         for(int i = fst2[u];i;i = es2[i].next)
     63         {
     64             int v = es2[i].to;
     65             maxx[v] = max(dis[v],maxx[u]);
     66             if(!vis2[v])
     67             {
     68                 q.push(v);
     69                 vis2[v] = 1;
     70             }
     71         }
     72     }
     73 }   
     74 int main()
     75 {
     76     scanf("%d%d",&n,&m);
     77     for(int i = 1;i <= n;i ++)
     78     {
     79         scanf("%d",&dis[i]);
     80         vis1[i] = 0;
     81         vis2[i] = 0;
     82         fst1[i] = 0;
     83         fst2[i] = 0;
     84         minn[i] = 2147483647;
     85         maxx[i] = 0;
     86     }
     87     for(int i = 1;i <= m;i ++)
     88     {
     89         int x,y,z;
     90         scanf("%d%d%d",&x,&y,&z);
     91         if(z == 1)
     92         {
     93             build1(x,y);
     94             build2(y,x);
     95         }
     96         else 
     97         {
     98             build1(x,y);build1(y,x);
     99             build2(x,y);build2(y,x);
    100         }
    101     }
    102     spfa1();
    103     spfa2();
    104     int ans = 0;
    105     for(int i = 1;i <= n;i ++)
    106     ans = max(ans,maxx[i] - minn[i]);
    107     printf("%d",ans);
    108     return 0;
    109 }

    不懂为什么要建反边~~

    还有来自神犇的暴力代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<vector>
     4 #include<algorithm>
     5 using namespace std;
     6 #define N 100002
     7 int n,m,s[N],maxn[N],minn[N],ans;
     8 vector<int>a[N],b[N];
     9 void dfs1(int g ,int h){//g为城市编号,h为当前城市的价格 
    10     minn[g]=min(h,minn[g]);//因为双向边可以来回,买价可以更低 
    11     for(int i=0;i<a[g].size();i++)
    12         if(h<minn[a[g][i]]) 
    13             dfs1(a[g][i],min(s[a[g][i]],h));    
    14 }
    15 void dfs2(int g ,int h){//同理
    16     maxn[g]=max(h,maxn[g]);
    17     for(int i=0;i<b[g].size();i++)
    18         if(h>maxn[b[g][i]]) 
    19             dfs2(b[g][i],max(s[b[g][i]],h));
    20 }
    21 int main(){
    22     scanf("%d%d",&n,&m);
    23     for(int i=1;i<=n;i++)
    24         scanf("%d",s+i);//每个城市的价格 
    25     for(int i=1,x,y,z;i<=m;i++){
    26         scanf("%d%d%d",&x,&y,&z);
    27         if(z==1)
    28             a[x].push_back(y),b[y].push_back(x);//单边 
    29         else
    30             a[x].push_back(y),a[y].push_back(x),b[x].push_back(y),b[y].push_back(x);//双边  
    31     }
    32     for(int i=1;i<=n;i++)
    33         maxn[i]=-1e9,minn[i]=1e9;
    34     dfs1(1,s[1]);//低价买
    35     dfs2(n,s[n]);//高价卖 
    36     for(int i=1;i<=n;i++)
    37         if(maxn[i]!=-1e9&&minn[i]!=1e9)
    38             ans=max(ans,maxn[i]-minn[i]);
    39     printf("%d
    ",ans);
    40     return 0;
    41 }
  • 相关阅读:
    mysql 约束条件介绍
    mysql 约束条件目录
    mysql 日期类型
    mysql float 浮点型
    mysql int 整数类型 解释显示宽度 和 存储宽度
    mysql 整数类型 数值类型 tinyint
    【洛谷P4096】Eden 的博弈树
    【GMOJ6824】英雄联盟
    【GMOJ6826】隔膜
    【POJ 2420】A Star not a Tree?
  • 原文地址:https://www.cnblogs.com/suishiguang/p/6413954.html
Copyright © 2011-2022 走看看