bzoj
洛谷一眼就會思路了吧。
把每個廚師拆點,拆分為他最多能要做的菜的個數,即∑p
i ∑pi
然後把每個菜向廚師的每個點連邊,表示這個菜是這個廚師做的第幾個菜。
考慮一下這個菜放在這個位置對於後面所有位置的影響就好了。
然後跑費用流就好了。
經蘿蔔提醒,上面這個東西就是scoi2007修車那道題目
然而這樣會掛,∑p
i≤32000
∑ pi
≤32000
,加上廚師個數
大概是∑pi
×m≤3200000
∑ pi
×m
≤3200000
有點**。
考慮一下費用流是怎麼做的:每次sp
fas pf
a找到一條費用最小的點,
在上述模型中,具有費用的唯一的邊就是從菜品到廚師拆出來的點,
並且我們知道,每次對於後面所有位置的影響需要乘上的倍數是遞增的。
所以我們從小往大連邊,保證每次sp
fas pf
a跑出來的結果一定是全域性的最優結果
每次增廣出來一條路徑,就對於增廣的這個廚師額外增加乙個點連進來就好了。
似乎有點簡單了?今天碼風好迷啊
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using
namespace
std;
#define ll long long
#define rg register
#define max 88888
inline
int read()
struct linee[max<<2];
int h[max],cnt=2;
inline
void add(int u,int v,int w,int fy)
;h[u]=cnt++;
e[cnt]=(line);h[v]=cnt++;
}queue
q;int pv[max],pe[max],s,t,flow,cost,dis[max];
bool inq[max];
bool spfa()
}inq[u]=false;
}if(dis[t]>=1e9)return
false;
int flow=1e9;
for(int i=t;i!=s;i=pv[i])flow=min(flow,e[pe[i]].w);
for(int i=t;i!=s;i=pv[i])e[pe[i]].w-=flow,e[pe[i]^1].w+=flow;
cost+=flow*dis[t];
return
true;
}int n,m,t[111][111],a[111],tot;
int bl[max];
int main()
while(spfa())
printf("%d\n",cost);
return
0;}
BZOJ 2879 美食節(費用流 動態加邊)
題意 有n道菜,每道菜需要b i 份,m個廚師,第j個廚師做第i道菜需要時間a i j 求做完所有菜,所有人等待的最小總時間。思路 設所有的菜為sum。乙個明顯的思路是將每個廚師拆成sum個點。然後sum個菜每個菜向每個廚師的每個點連邊,表示該道菜為該廚師第幾個做。由於這樣資料太大。動態加邊。每次增...
C 之路高階 bzoj2879(美食節)
time limit 10 sec memory limit 512 mb submit 1304 solved 702 submit status discuss 輸入檔案的第1行包含兩個正整數n和m,表示菜品的種數和廚師的數量。第2行包含n個正整數,其中第i個數為pi,表示點第i種菜品的人數。接...
NOI2012 美食節 費用流
題目描述 題解 一開始按照修車那題的思路搞了個費用流,就是把廚師拆成tim個點,表示他是倒數第幾個做的,然後邊權就是對後面的人的代價和,然後t到飛起。原因是直接把圖建出來導致圖的規模過大,然後spfa就死了。所以我們可以動態加邊,每增廣一次就加乙個點。include include include ...