題目描述
申奧成功後,布布經過不懈努力,終於成為奧組委下屬公司人力資源部門的主管。布布剛上任就遇到了乙個難題:為即將啟動的奧運新專案招募一批短期志願者。經過估算,這個專案需要n 天才能完成,其中第i 天至少需要ai 個人。 布布通過了解得知,一共有m 類志願者可以招募。其中第i 類可以從第si 天工作到第ti 天,招募費用是每人ci 元。新官上任三把火,為了出色地完成自己的工作,布布希望用盡量少的費用招募足夠的志願者,但這並不是他的特長!於是布布找到了你,希望你幫他設計一種最優的招募方案。
輸入輸出格式
輸入格式:
第一行包含兩個整數n, m,表示完成專案的天數和可以招募的志願者的種類。 接下來的一行中包含n 個非負整數,表示每天至少需要的志願者人數。 接下來的m 行中每行包含三個整數si, ti, ci,含義如上文所述。為了方便起見,我們可以認為每類志願者的數量都是無限多的。
輸出格式:
僅包含乙個整數,表示你所設計的最優方案的總費用。
題解:最小費用流還是很明顯的,關鍵在於如何建模。
我們逐天考慮一下:
首先,雇員的數量是不限的,每天的需求量是固定的。
這道題難就難在每個人的工作時間不是一天,而是第 $[s_,t_]$ 天之間,這就讓我們很難建出約束關係。
我們考慮這麼做:
首先將每一天看作是乙個節點,向下一天連一條容量為 $inf-need_$ 的邊,費用為 $0$。
再將每個 $[s_,t_]$ 中的 $s_$ 向 $t_+1$ 連一條邊,容量無限,費用為每個人所需費用。
特別地,我們將起點到 1 號點,$n$ 號點向終點連的邊容量為 $inf$,這樣的話程式在優先跑完費用為 $0$ 的邊後就會跑那些需要花費的邊來滿足題目要求來補足那些流量不夠的邊。
總體來說,還是不太好想的。
code:
#include#include#include#include#include#includeusing namespace std;
void setio(string a)
const int maxn=2000;
const int inf=1000000+23666;
typedef long long ll;
int s,t,n,m;
struct edge
};struct mcmf
int spfa()}}
}if(d[t]==inf)return 0;
f=flow2[t];
flow+=f;
int u=edges[a[t]].from;
edges[a[t]].cap-=f;
edges[a[t]^1].cap+=f;
while(u!=s)
ans+=(ll)(d[t]*f);
return 1;
}int maxflow()
ll getcost()
}t;int main()
for(int i=1;i<=m;++i)
t.maxflow();
printf("%lld",t.getcost());
return 0;
}
NOI 2008 志願者招募
考慮用 p i 表示第 i 天實際招收的人數,我們假設我們有三種志願者,分別是 1 to 2,1 to 3 2 to 3 我們招手的人數分別是 b 1,b 2,b 3 那麼第一天實際人數就是 p 1 b 1 b 2 geq a 1 同理我們把三個不等式寫出來 b 1 b 2 ge a 1 b 1 b...
NOI2008志願者招募
申奧成功後,布布經過不懈努力,終於成為奧組委下屬公司人力資源部門的主管。布布剛上任就遇到了乙個難題 為即將啟動的奧運新專案招募一批短期志願者。經過估算,這個專案需要n 天才能完成,其中第i 天至少需要ai 個人。布布通過了解得知,一共有m 類志願者可以招募。其中第i 類可以從第si 天工作到第ti ...
NOI2008 志願者招募
oj題號 bzoj1061 題目大意 有 n 個任務,m 個志願者,完成每個任務 i 至少需要 a i 個人,每個人只有在 s i 到 t i 的時候有空,並需要被支付 c i 的報酬,求完成所有任務的最小支出。思路 先挖空後補空 將每個時間抽象成點,並在時間軸的兩端增加源匯 s 和 t 每個相鄰的...