zoukankan      html  css  js  c++  java
  • [APIO2017]商旅 0/1分数规划

    ~~~题面~~~

    题解:

    upd: 在洛谷上被Hack了。。。思路应该是对的,代码就别看了

    感觉有个地方还是非常妙的,就是因为在x买东西,在y卖出,就相当于直接从x走向了y,因为经过中间的城市反正也不会造成任何影响。

    所以建图就可以直接把所有城市两两连边,然后直接枚举找出使得在x买东西,在y卖出的利润最大化的物品,并将利润作为权值,(a[i])

    再floyd找出x到y的最短路径(这大概就算用到城市可以重复经过的条件了吧)作为代价,(b[i])

    接下来就和[HNOI2009]最小圈非常类似了。

    只不过这里是要找最大利润,而我们是用spfa找负环,所以可以对边权取相反数,(当然你也可以不变边权找正环)

    此外还有一个需要注意的地方,

    如果你是二分小数自然没有任何问题,

    但是如果你是二分整数就要注意判断0环了(因为答案是向下取整的),因为如果你二分小数的话,反正你会多二分几次来保证精度,所以不判断是没有什么问题的,

    但是整数不一样,所以要判断0环,方法也很简单,在dfs版spfa里面的判断条件上加上=就可以了

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define R register int
      4 #define AC 150
      5 #define ac 21000
      6 #define getchar() *o++
      7 #define inf 2139062143
      8 char READ[5001000],*o=READ;
      9 int n,m,l,mid,maxn;
     10 int buy[AC][AC*10],sale[AC][AC*10],s[AC][AC],f[AC][AC],dis[ac];
     11 int date[ac],Next[ac],Head[AC],length[ac],tot;
     12 bool vis[AC],flag;
     13 /*想了很久如何处理异地交易的问题,因为中间走过的路程会被忽略,
     14 所以实际上就相当于直接从买入地x走到了卖出地y,
     15 所以直接两两连边,因为反正可以重复经过,所以走一条边就相当于略过了中间的所有边,
     16 然后为了尽量节省时间,所以先处理出任意两点之间的最短路,因为不管怎么走收益不变,
     17 但代价变了,所以连边要连最短路,所以先floyd处理一下,再把结果连成边,
     18 不过利益不变的前提是买同一种商品,但是商品不止一种,所以还要处理出最大收益,
     19 因为地点都已经固定了,所以这个时候就只要枚举一下买哪种划得来了,
     20 标准就是买卖单个的收入就行了
     21 然后动态改一下权值就好了,dfs版spfa找负环*/
     22 inline int read()
     23 {
     24     int x=0;char c=getchar();bool z=false;
     25     while(c > '9' || c < '0') {if(c == '-') z=true; c=getchar();}
     26     while(c >= '0' && c <= '9') x=x*10+c-'0',c=getchar();
     27     if(!z) return x;
     28     else return -x;
     29 }
     30 
     31 inline void add(int f,int w)
     32 {
     33     date[++tot]=w,Next[tot]=Head[f],Head[f]=tot;
     34 }
     35 
     36 inline void upmin(int &a,int b)
     37 {
     38     if(b < a) a = b; 
     39 }
     40 
     41 inline void upmax(int &a,int b)
     42 {
     43     if(b > a) a = b;
     44 }
     45 
     46 void pre()
     47 {
     48     int a,b,c;
     49     n=read(),m=read(),l=read();
     50     memset(f,127,sizeof(f));
     51     for(R i=1;i<=n;i++)
     52     {
     53         f[i][i]=0;
     54         for(R j=1;j<=l;j++)
     55             buy[i][j]=read() , sale[i][j]=read();
     56     }
     57     for(R i=1;i<=m;i++)
     58     {
     59         a=read(),b=read(),c=read();
     60         upmin(f[a][b],c);//这里就要upmin。,,,,不然可能会被不优的边覆盖
     61     }
     62 }
     63 
     64 void init()
     65 {
     66     /*for(int i=1;i<=n;i++)
     67     {
     68         for(int j=1;j<=n;j++)
     69             printf("%d ",f[i][j]);
     70         printf("
    ");
     71     }
     72     printf("!!!
    ");*/
     73     for(R k=1;k<=n;k++)    
     74         for(R i=1;i<=n;i++)
     75         {
     76             if(f[i][k] == inf) continue;
     77             for(R j=1;j<=n;j++)
     78                 if(f[k][j] != inf) upmin(f[i][j] , f[i][k] + f[k][j]);
     79         }//怕爆了
     80     for(R i=1;i<=n;i++)//枚举起点
     81         for(R j=1;j<=n;j++)//枚举终点
     82         {
     83             if(i == j) continue;
     84             if(f[i][j] == inf) continue; 
     85             for(R k=1;k<=l;k++) //枚举买哪种
     86             {
     87                 if(sale[j][k] == -1 || buy[i][k] == -1) continue;
     88                 upmax(s[i][j],sale[j][k] - buy[i][k]);//获取利润                                                                                                                                                                                                                                                    
     89                 upmax(maxn,s[i][j] / f[i][j]);
     90             }
     91         }
     92     /*for(int i=1;i<=n;i++)
     93     {
     94         for(int j=1;j<=n;j++)
     95             printf("%d ",f[i][j]);
     96         printf("
    ");
     97     }
     98    // printf("---------------
    ");
     99     printf("
    ");
    100     for(int i=1;i<=n;i++)
    101     {
    102         for(int j=1;j<=n;j++)
    103             printf("%d ",s[i][j]);
    104         printf("
    ");
    105     }*/
    106     for(R i=1;i<=n;i++)
    107         for(R j=1;j<=n;j++)
    108         {
    109             if(i == j) continue;
    110             if(f[i][j] == inf) continue;//error,,,这里不能加上!s[i][j],虽然没有利润,但仍然可以起到连接作用
    111             add(i,j);
    112         }
    113 }
    114 
    115 void spfa(int x)
    116 {
    117     int now;
    118     vis[x]=true;
    119     for(R i=Head[x]; i ;i=Next[i])
    120     {
    121         now=date[i];
    122         if(dis[now] >= dis[x] + length[i])//找负环肯定是最短路啊
    123         {//加个等号判0环?
    124             if(vis[now]) {flag=true;break;}
    125             dis[now] = dis[x] + length[i];
    126             spfa(now);
    127         }
    128     }
    129     vis[x]=false;
    130 }
    131 
    132 bool check()
    133 {
    134     int now;
    135     flag=false;
    136     memset(dis,0,sizeof(dis));
    137     for(R i=1;i<=n;i++)
    138         for(R j=Head[i]; j ;j=Next[j])
    139         {
    140             now=date[j];
    141             length[j]=mid * f[i][now] - s[i][now];//因为要用找负环的方法找正环,所以边权取相反
    142         }//error,,是f[i][now]
    143     for(R i=1;i<=n;i++)
    144     {
    145         spfa(i);
    146         if(flag) return true;
    147     }
    148     return false;
    149 }
    150 
    151 void half()
    152 {
    153     int l=0,r=maxn;
    154     while(r - l > 1)
    155     {
    156         mid=(l + r) / 2;
    157         if(check()) l=mid;
    158         else r=mid;
    159     }
    160     if(r > l)
    161     {
    162         mid=r;
    163         if(check()) printf("%d
    ",r);
    164         else printf("%d
    ",l);
    165     }
    166     else printf("%d
    ",l);
    167 }
    168 
    169 int main()
    170 {
    171 //    freopen("in.in","r",stdin);
    172     fread(READ,1,5000000,stdin);
    173     pre();
    174     init();
    175     half();
    176 //    fclose(stdin);
    177     return 0;
    178 }
  • 相关阅读:
    SAP PI 如何实现消息定义查询
    EWM与ERP交互程序
    ITS Mobile Template interpretation failed. Template does not exist
    SAP Material Flow System (MFS) 物料流系统简介
    SAP EWM Table list
    EWM RF 屏幕增强
    SAP EWM TCODE list
    SAP扩展仓库管理(SAPEWM)在线研讨会笔记
    ERP与EWM集成配置ERP端组织架构(二)
    EWM RF(Radio Frequency)简介
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9143677.html
Copyright © 2011-2022 走看看