codevs 1237 餐巾計畫問題

2021-06-28 13:48:28 字數 1589 閱讀 8362

引用《24題》:

把每天分為二分圖兩個集合中的頂點xi,yi,建立附加源s匯t。

1、從s向每個xi連一條容量為ri,費用為0的有向邊。

2、從每個yi向t連一條容量為ri,費用為0的有向邊。

3、從s向每個yi連一條容量為無窮大,費用為p的有向邊。

4、從每個xi向xi+1(i+1<=n)連一條容量為無窮大,費用為0的有向邊。

5、從每個xi向yi+m(i+m<=n)連一條容量為無窮大,費用為f的有向邊。

6、從每個xi向yi+n(i+n<=n)連一條容量為無窮大,費用為s的有向邊。

求網路最小費用最大流,費用流值就是要求的最小總花費。

【建模分析】

這個問題的主要約束條件是每天的餐巾夠用,而餐巾的**可能是最新購買,也可能是前幾天送洗,今天剛剛洗好的餐巾。每天用完的餐巾可以選擇送到快洗部或慢洗部,或者留到下一天再處理。

經過分析可以把每天要用的和用完的分離開處理,建模後就是二分圖。二分圖x集合中頂點xi表示第i天用完的餐巾,其數量為ri,所以從s向xi連線容量為ri的邊作為限制。y集合中每個點yi則是第i天需要的餐巾,數量為ri,與t連線的邊容量作為限制。每天用完的餐巾可以選擇留到下一天(xi->xi+1),不需要花費,送到快洗部(xi->yi+m),費用為f,送到慢洗部(xi->yi+n),費用為s。每天需要的餐巾除了剛剛洗好的餐巾,還可能是新購買的(s->yi),費用為p。

在網路上求出的最小費用最大流,滿足了問題的約束條件(因為在這個圖上最大流一定可以使與t連線的邊全部滿流,其他邊只要有可行流就滿足條件),而且還可以保證總費用最小,就是我們的優化目標。

總時間耗費: 2598ms 

總記憶體耗費: 876b

#include#include#include#include#includeusing namespace std;

const int maxn = 5000 + 10;

const int inf = 1e9 + 7;

struct edge ;

int n, s, t;

vectorg[maxn];

vectoredges;

void addedge(int from, int to, int cap, int cost) );

edges.push_back((edge));

int m = edges.size();

g[from].push_back(m-2);

g[to].push_back(m-1);

}int d[maxn], p[maxn], a[maxn];

bool inq[maxn];

bool bellmanford(int& cost)

}} }

if(d[t] == inf) return 0;

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

int x = t;

while(x != s)

return 1;

}int mincostmaxflow()

int main()

cout << mincostmaxflow() << endl;

return 0;

}

P1251 餐巾計畫問題

題面 一道特別棒的費用流好題,思路非常巧妙 對於每一天,我們分為早上和晚上兩個節點 每天早上會消耗 r i 條乾淨的毛巾,可以視為流向匯點,所以我們向匯點連一條流量為 r i 費用為 0 的邊 每天晚上會產生 r i 條髒毛巾,可以視為從源點流出,所以我們從源點連一條流量為 r i 費用為 0 的邊...

洛谷 1251 餐巾計畫問題

題鏈 題解 一點啟示 建圖時要考慮到流量問題,即為了方便使用最小費用最大流演算法,要把流量最大時為最終目的考慮進建圖。拆點,每天拆為兩個點i,i 表示每天開始和每天結束 s,i,ai,p 在第i天最多買ri個餐巾,花費為p i,t,ai,0 第i天要用ai塊餐巾 s,i ai,0 第i天用剩的ai塊...

Luogu P1251 餐巾計畫問題

不得不說這是一道非常好的費用流神題。建圖清新自然,構建沒有毒瘤。實為網路流24題中難得一見的好題。我們考慮一下網路流的建圖。首先拆點並建立超級源點ss和超級匯點 t 常見套路 我們把每一天拆成早上 x i 和晚上 y i 然後考慮每天早上要向 t 提供 r i 條乾淨的餐巾,而 s 要向每天晚上提供...