[9018_1400]利润

题目描述

        GreatLWH成为了著名品牌的一个经销商,由于经营有方,他创造了商品销售上的奇迹——就是进多少卖多少。为了可以获得更多的利润,他决定从其他经销商那里进货。
 
        进货的要遵循以下规则:
        1. 有一个顶级经销商,他有无限的库存,他的出货价总是恒定的。
        2. 其他的经销商只能间接或直接从顶级经销商进货,而且一个经销商向其他经销商进货的量应等于向其他经销商出货的量(即假设经销商都只会把商品卖给别的经销商)(顶级经销商和GreatLWH例外)。
        3. 经销商之间有单向的买卖关系,一个经销商v会向u要求进货,当且仅当存在u→v的单向买卖关系,同理,u会向v 出货也是要求当且仅当存在u→v的单向买卖关系。
        4. 代理一个产品最主要的就是获利,一个经销商将商品卖个另一个经销商时会以成本价上浮x%的价格卖给购买方(例外的是顶级经销商有着固定的出货价,他的出货价不会随着进货价而变动,或者说因为他就是厂家,他的成本价是一定的,而且他会不加价的买给其他经销商)。由于经销商之间亲密程度不同,所以每一条单向买卖关系的加价幅度(即x%)不一定相同,而且对于一个单向买卖关系<u_i, v_i>而言,经销商u_i 最多愿意卖给v_i的商品数为c_i。
 
        根据以上规则,GreatLWH想知道他最多可以拿到多少的商品,而由于售价是一定的,GreatLWH想要以尽量低的总成本购进尽量多的商品。他发现经销商的关系有点小复杂,编程解决又太水了,所以他决定把这个简单的任务交给你。
 
        {你大可以认为货物是一批一批地依次从顶级经销商流通到GreatLWH手上。即上一批货物没有到达GreatLWH时,新一批货物不会从顶级经销商那里发出。}

输入

        第一行n,m,s表示共有n个经销商,m条单向买卖关系,顶级经销商的出货价格为s(其中顶级经销商的编号为1,GreatLWH的编号为n)
 
        接下来m行,每行4个正整数:u,v,c,x表示经销商u和v之间存在最多销售c和加价x%的单向买卖关系。
 
        根据题意,输入数据保证顶级经销商卖给其他经销商的价格总是恒定的,即x=0。
 
        数据保证没有重边。

输出

        第一行一个数sum,表示最多的进货量。
 
        第二行一个数cost,表示获得最多进货量的最小成本。
 
        进货成本精确到一位小数。
 
        无法进货时输出:
 
        0
 
        0.0

样例输入

3 3 5
1 2 4 0
2 3 3 100
1 3 3 0

样例输出

6
45.0

提示

数据满足n<=1,500,m<d=20,000,答案在int范围内。
(a,b,c,d)表示从a向b连容量为c,费用为d的边

 虽然题目看起来很长,但其实很简单,按题意建边,跑费用流

唯一麻烦的是利润上浮x%,我们可以化乘为加(log(x)+log(y)=log(xy))

建(ui,vi,ci,log(1+x%))的边,最后计算答案时算exp(费用)*容量

#include<iostream> 
#include<cstdio> 
#include<cstring> 
#include<cmath> 
#define eps 1e-8 
using namespace std; 
struct data{ 
int to,cap,next;double cost; 
}g[80001]; 
int h[2101],k=1,used[2101],que[100000],head,tail,last[2101];double ans=0.0,d[2101];int flow=0; 
double INF=999999999.99; 
inline int read(){  
    int x; bool f; char c;  
    for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');  
    for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');  
    return f?-x:x;  
}  
void add(int from,int to,int cap,double cost) 
{ 
    g[++k].next=h[from];h[from]=k;g[k].to=to;g[k].cap=cap;g[k].cost=cost; 
    g[++k].next=h[to];h[to]=k;g[k].to=from;g[k].cap=0;g[k].cost=-cost; 
} 
bool spfa(int s,int t) 
{ 
    memset(last,0,sizeof(last)); 
    fill(d,d+2000,INF); 
    memset(used,0,sizeof(used)); 
    head=tail=50000;que[tail++]=s;used[s]=1;d[s]=0.0; 
    while(head<=tail) 
    { 
        int u=que[head++]; 
        for(int i=h[u];i;i=g[i].next) 
        { 
            if(g[i].cap&&d[u]+g[i].cost+eps<d[g[i].to]) 
            { 
            d[g[i].to]=d[u]+g[i].cost;last[g[i].to]=i; 
            if(!used[g[i].to]) 
                { 
                    if(d[g[i].to]+eps<d[que[head]])que[--head]=g[i].to; 
                    else que[tail++]=g[i].to;used[g[i].to]=1; 
                } 
            } 
        } 
        used[u]=0; 
    } 
    if(abs(d[t]-INF)<=eps)return false; 
    return true; 
} 
void mcf(int t) 
{ 
    int minn=INF;double tot=0; 
    for(int i=last[t];i;i=last[g[i^1].to])minn=min(minn,g[i].cap); 
    for(int i=last[t];i;i=last[g[i^1].to]) 
    { 
        tot+=g[i].cost; 
        g[i].cap-=minn;g[i^1].cap+=minn; 
    } 
    flow+=minn;ans+=exp(tot)*minn; 
} 
int main() 
{ 
    int n=read(),m=read(),s=read(); 
    for(int i=1;i<=m;i++) 
    { 
        int u=read(),v=read(),c=read(),w=read();add(u,v,c,log((double)w*0.01+1.00)); 
    } 
    while(spfa(1,n))mcf(n); 
    printf("%d
%.1lf",flow,ans*s); 
    return 0; 
 }  
原文地址:https://www.cnblogs.com/lher/p/7118503.html