【題解】
費用流:
首先確定:每一單位的流量代表一位廚師做乙份菜品,費用代表花費的時間
每位廚師做同一道菜,每乙份時間也是不同的,因此將每個廚師拆成p個點
建邊需要確定的費用與做菜順序有關,而後做的菜對先做的菜是沒有影響的,所以倒著處理,拆成的第i個點表示每位廚師做的倒數第i道菜
建圖:s -> n種菜品 容量為pi,費用為0
第i種菜品 -> 第j位廚師拆成的第k個點 容量為1,費用為 k*t[i][j]
第j位廚師拆成的第k個點 -> t 容量為1,費用為0
每次增流只會增1個單位,所以共增流p次,邊數約為m*p*n,因此,複雜度為:o(m*n*p^2) 會tle
動態建點:
開始時只允許每個廚師做"倒數第一道菜",只為做完當前菜的那個廚師安排下一道菜,因為更新的流不會從t出發,所以該演算法正確
【**】
#include#include#define inf 1000000000
int u[80000]=,v[80000]=,cap[80000]=,flow[80000]=,cost[80000]=,first[1000]=,next[80000]=;
int t[50][150]=,q[1000000]=,d[1000]=,p[1000]=,hash[1000]=,id[1000]=,len[50]=;
int e=0;
void tj(int x,int y,int z,int c)
int fan(int x)
int main()
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%d",&t[i][j]);
for(i=1;i<=m;i++)
tj(node,t,1,0);
tj(t,node,0,0);
} for(;count>0;count--)
d[s]=0;
hash[s]=1;
head=0;
tail=1;
q[0]=s;
while(headd[u[i]]+cost[i]&&cap[i]>flow[i])
}hash[q[head++]]=0;
} a=inf;
for(i=t;i!=s;i=u[p[i]])
if(a>cap[p[i]]-flow[p[i]]) a=cap[p[i]]-flow[p[i]];
for(i=t;i!=s;i=u[p[i]])
f+=a*d[t];
x=u[p[t]];
id[++node]=id[x];
len[id[x]]++;
for(i=1;i<=n;i++)
tj(node,t,1,0);
tj(t,node,0,0);
} printf("%d",f);
return 0;
}
費用流 動態加邊 NOI2012 美食節
輸入檔案的第1行包含兩個正整數n和m,表示菜品的種數和廚師的數量。第2行包含n個正整數,其中第i個數為pi,表示點第i種菜品的人數。接下來有n行,每行包含m個非負整數,這n行中的第i行的第j個數為ti,j,表示第j個廚師製作第i種菜品所需的時間。輸入檔案中每行相鄰的兩個數之間均由乙個空格隔開,行末均...
NOI2012 美食節 費用流
題目描述 題解 一開始按照修車那題的思路搞了個費用流,就是把廚師拆成tim個點,表示他是倒數第幾個做的,然後邊權就是對後面的人的代價和,然後t到飛起。原因是直接把圖建出來導致圖的規模過大,然後spfa就死了。所以我們可以動態加邊,每增廣一次就加乙個點。include include include ...
NOI2012 美食節(網路流)
本題是修車的資料加強版 有數量限制和花費,考慮費用流建模 顯然,源點連線每個菜,流量為 p i 廚師連向匯點,流量為 inf 但是菜 i 和廚師 j 在不同時間的花費是不同的,具體來說,當它是倒數第 k 道菜時,它的花費為 k times a 將廚師拆點,分別對應倒數第 k 道菜,連線菜和廚師,流量...