NOI2012 美食節(費用流 動態開點)

2021-07-02 01:39:00 字數 1470 閱讀 1167

【題解】

費用流:

首先確定:每一單位的流量代表一位廚師做乙份菜品,費用代表花費的時間 

每位廚師做同一道菜,每乙份時間也是不同的,因此將每個廚師拆成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 道菜,連線菜和廚師,流量...