網路流之最小費用最大流 P1251 餐巾計畫問題

2022-05-03 14:09:19 字數 3199 閱讀 1228

乙個餐廳在相繼的 nn 天裡,每天需用的餐巾數不盡相同。假設第 ii 天需要 r_iri​塊餐巾( i=1,2,...,n)。餐廳可以購買新的餐巾,每塊餐巾的費用為 pp 分;或者把舊餐巾送到快洗部,洗一塊需 m 天,其費用為 f 分;或者送到慢洗部,洗一塊需 nn 天(n>mn>m),其費用為 ss 分(ss每天結束時,餐廳必須決定將多少塊髒的餐巾送到快洗部,多少塊餐巾送到慢洗部,以及多少塊儲存起來延期送洗。但是每天洗好的餐巾和購買的新餐巾數之和,要滿足當天的需求量。

試設計乙個演算法為餐廳合理地安排好 nn 天中餐巾使用計畫,使總的花費最小。程式設計找出乙個最佳餐巾使用計畫。

輸入格式:

由標準輸入提供輸入資料。檔案第 1 行有 1 個正整數 nn,代表要安排餐巾使用計畫的天數。

接下來的 nn 行是餐廳在相繼的 nn 天裡,每天需用的餐巾數。

最後一行包含5個正整數p,m,f,n,sp,m,f,n,s。pp 是每塊新餐巾的費用; mm 是快洗部洗一塊餐巾需用天數; ff 是快洗部洗一塊餐巾需要的費用; nn 是慢洗部洗一塊餐巾需用天數; ss 是慢洗部洗一塊餐巾需要的費用。

輸出格式:

將餐廳在相繼的 n 天裡使用餐巾的最小總花費輸出

輸入樣例#1: 複製

3

1 7 5

11 2 2 3 1

輸出樣例#1: 複製

134

n<=2000

ri<=10000000

p,f,s<=10000

時限4s

const

int inf = 0x3f3f3f3f

;const

int maxn = 1000 + 10

;struct

edge

};vector

e;vector

g[maxn];

int a[maxn];//

找增廣路每個點的水流量

int p[maxn];//

每次找增廣路反向記錄路徑

int d[maxn];//

spfa演算法的最短路

int inq[maxn];//

spfa演算法是否在佇列中

intn, m;

void init(int

n)void addedge(int u, int v, int c, int

cost)

bool bellman(int s, int t, int& flow, long

long &cost)

//bellman 演算法入隊

} }

}if(d[t] == inf)return

false;//

找不到增廣路

flow += a[t];//

最大流的值,此函式引用flow這個值,最後可以直接求出flow

cost += (long

long)d[t] * (long

long)a[t];//

距離乘上到達匯點的流量就是費用

for(int u = t; u != s; u = e[p[u]].u)//

逆向存邊

return

true;}

int mincostmaxflow(int s, int t, long

long &cost)

這個題目建圖很難想,開始一點思路都沒有,看了看題解。

建圖:這個是把每一天拆成了兩個點,乙個上午點和乙個下午點。

下午點都和源點相連表示一天的結束,上午點和匯點相連,表示需要的餐巾數量。

與源點和匯點相連的點的cap都設定成這一天需要的餐巾數量,這個來限制送去快洗和慢洗的毛巾數。

然後再去處理3+1,3表示快洗,慢洗,新買,1表示不洗。因為之前以及被限制過了,

所以這裡的不需要再去考慮有多少髒毛巾,這裡的cap應該設定成inf,因為一次可以洗無數條毛巾。

這個不洗的要好好處理,這個不洗表示直接積累到下一天,那麼就說明,這個的cost=0,

但是我們會疑惑,如果這樣會不會影響到網路流? 其實這個不會,因為餐巾的積累會往下一天的晚上傳遞,意思

是說,這個餐巾不會算作這一天需要的餐巾數,但是那為什麼還要連邊呢?這個連邊會讓它往下一天傳遞,

那麼餐巾積累,之後可以考慮一起洗掉。一起洗一堆和一次洗一條所用的時間是一樣的,

所以如果我們之後再堆在一起洗也許會更優。

#include #include 

#include

#include

#include

#include

#include

#define inf 0x3f3f3f3f

using

namespace

std;

typedef

long

long

ll;const

int maxn =1e4;

struct

node

};vector

e;vector

g[maxn];

ints, t;

void add(int u, int v, int cap, int

cost)

intd[maxn], inq[maxn], a[maxn], p[maxn];

bool bellman(ll&cost)}}

}if (d[t] == inf) return

false

; cost += 1ll * d[t] * 1ll *a[t];

//printf("%lld\n", cost);

for(int i=t;i!=s;i=e[p[i]].from

)

return

true;}

void maxflow(ll &cost)

intmain()

intq, m, f, n, g;

cin >> q >> m >> f >> n >>g;

for (int i = 1; i <= n; i++)

if (i + m <=n)

if (i + n <=n)

add(s, n +i, inf, q);

}ll cost = 0

; maxflow(cost);

printf(

"%lld\n

", cost);

return0;

}

網路流之 最小費用最大流

學習最小費用最大流前,需要學習最大流演算法。在最大流演算法中,沒有考慮邊的費用問題。在mincostmaxflow中,引入了費用的概念 cij表示邊 i,j 單位流量的費用。在滿足流量 v f 的同時,並且要求費用最少。最小費用最大流的迭代演算法 1.求出從s到t的最小費用通路 spfa 和通路的最...

網路流 最小費用最大流

q 為什麼突然想搞網路流?a 迫於tham 蛤mu的淫威 用最短路演算法求出s t的路徑 把路徑要摳出來,而且每條邊要有容量 算一下路徑裡面的可以流過的最大的流量 發現此時的花費就是 dis t flow 累加即可.重複1 3直到不能夠到達t.include include include incl...

網路流之最小費用流

這是一道模板題。給定乙個圖,每條邊有容量和費用,使用每條邊的單位流量需要支付特定的費用。給定源點 1和匯點 n,求圖的最大流和最大流需要支付的最小費用。第一行兩個整數n,m,表示有 n 個點 m 條邊。從第二行開始的之後 m 行,每行四個整數s i t i c i w i 表示一條從 s i 到 t...