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

    原题链接:https://www.luogu.org/problem/show?pid=1073#sub

    猛的一看这题,诶我怎么在哪见过。。

    哦是双向SPFA那题。。然后凭记忆xjb搞了一下就A了。。

    翻了一下我codevs的记录,诶我在半年之前写过这题?我怎么不记得了?

    坑点略多就是了。。有些地方必须用奇怪的写法才可以,否则绝对爆0。。。。

    这题题意要求我们求出能赚取的最大差价。说到差价很好想了,肯定是卖出价-买入价=差价。

    题目规定了从点1出发到点n,我的做法是,从起点正向跑一次spfa,可以求出所有的买入价的最小值。然后从终点反向跑一次spfa,可以求出所有卖出价的最大值。最后维护一下最大差价便是答案。

    稍微想一下便能发现这个算法正确性是显然的。至少我这么认为。

    建图的时候有单向边有双向边,判断一下就好了。

    (我一直弄不明白判断为啥if不行swicth可以。。。)

    参考代码:

      1 #include <iostream>
      2 #include <queue>
      3 #include <cstring>
      4 #include <cstdio>
      5 #define maxn 500001
      6 #define INF 0x7fffffff / 2
      7 #define debug cout << "OK" << endl;
      8 using namespace std;
      9 struct Edge{
     10     int from,to,dis;
     11 };
     12 int ball_val[maxn];
     13 int n,m,u,v,dir,w;
     14 int ans = -INF;
     15 Edge pos_edge[maxn];
     16 Edge nag_edge[maxn];
     17 int pos_head[maxn],pos_tot=0;
     18 int nag_head[maxn],nag_tot = 0;
     19 int pos_dis[maxn];
     20 int nag_dis[maxn];
     21 bool inq[maxn];
     22 int read(){
     23     int num = 0;
     24     char c;
     25     bool flag = false;
     26     while ((c = getchar()) == ' ' || c == '
    ' || c == '
    ');
     27     if (c == '-')
     28         flag = true;
     29     else
     30         num = c - '0';
     31     while (isdigit(c = getchar()))
     32         num = num * 10 + c - '0';
     33     return (flag ? -1 : 1) * num;
     34 }
     35 void pos_add_edge(int from,int to,int dis){
     36     pos_edge[++pos_tot].from=pos_head[from];
     37     pos_edge[pos_tot].to = to;
     38     pos_edge[pos_tot].dis = dis;
     39     pos_head[from] = pos_tot;
     40 }
     41 
     42 void nag_add_edge(int from,int to,int dis){
     43     nag_edge[++nag_tot].from=nag_head[from];
     44     nag_edge[nag_tot].to = to;
     45     nag_edge[nag_tot].dis = dis;
     46     nag_head[from] = nag_tot;
     47 }
     48 void pos_spfa(int s){
     49     queue<int> q;
     50     memset(inq,false,sizeof(inq));
     51     q.push(s);
     52     inq[s] = true;
     53     pos_dis[1] = ball_val[1];
     54     for (register int i=2;i<=m;i++)
     55         pos_dis[i] = INF;
     56     while (!q.empty()){
     57         int u = q.front();
     58         q.pop();
     59         inq[u] = false;
     60         for (register int i=pos_head[u];i!=0;i=pos_edge[i].from){
     61             int v = pos_edge[i].to;
     62             int w = pos_edge[i].dis;
     63             if (pos_dis[v]>w || pos_dis[v]<pos_dis[u]){
     64                 pos_dis[v] = min(w,pos_dis[u]);
     65                 if (!inq[v]){
     66                     inq[v] = true;
     67                     q.push(v);
     68                 }
     69             }
     70         }
     71     }
     72 }
     73 void nag_spfa(int s){
     74     queue<int> q;
     75     memset(inq,false,sizeof(inq));
     76     q.push(s);
     77     inq[s] = true;
     78     nag_dis[m] = ball_val[m];    
     79     for (register int i=1;i<m;i++)
     80         nag_dis[i] = -INF;
     81 
     82     while (!q.empty()){
     83         int u = q.front();
     84         q.pop();
     85         inq[u] = false;
     86         for (register int i=nag_head[u];i!=0;i=nag_edge[i].from){
     87             int v = nag_edge[i].to;
     88             int w = nag_edge[i].dis;
     89             if (nag_dis[v]<w || nag_dis[v]<nag_dis[u]){
     90                 nag_dis[v] = max(w,nag_dis[u]);
     91                 if (!inq[v]){
     92                     inq[v] = true;
     93                     q.push(v);
     94                 }
     95             }
     96         }
     97     }
     98 }
     99 
    100 int main(){
    101     n = read();m = read();
    102     for (register int i=1;i<=n;i++)
    103         ball_val[i] = read();
    104     for (int i=1;i<=m;i++){
    105         u =read();v = read();dir = read();
    106         switch(dir){
    107             case 1:
    108                 pos_add_edge(u,v,ball_val[v]);
    109                 nag_add_edge(v,u,ball_val[u]);
    110                 break;
    111             case 2:
    112                 pos_add_edge(u,v,ball_val[v]);
    113                 nag_add_edge(v,u,ball_val[u]);
    114                 pos_add_edge(v,u,ball_val[u]);
    115                 nag_add_edge(u,v,ball_val[v]);
    116                 break;
    117         }
    118     }
    119     pos_spfa(1);nag_spfa(n);
    120     for (register int i=1;i<=n;i++){
    121         w = nag_dis[i] - pos_dis[i];
    122         ans = max(ans,w);
    123     }    
    124     printf("%d",ans);
    125     return 0;
    126 }
  • 相关阅读:
    Ubuntu中root用户和user用户的相互切换
    Linux扩展权限
    計蒜客/填志愿(匈牙利算法)
    計蒜課/排澇(Edmond-Karp)
    計蒜客/數正方形(dp)
    51nodcontest#24 A(xjb)
    計蒜客/节食的限制(01背包)
    計蒜客/小教官(xjb)
    atcoder#073D(枚舉)
    Educational Codeforces Round 20 C(math)
  • 原文地址:https://www.cnblogs.com/OIerShawnZhou/p/7637898.html
Copyright © 2011-2022 走看看