BZOJ 2879 美食节(费用流-动态加边)
生活随笔
收集整理的這篇文章主要介紹了
BZOJ 2879 美食节(费用流-动态加边)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接:http://61.187.179.132/JudgeOnline/problem.php?id=2879
題意:有n道菜,每道菜需要b[i]份,m個廚師,第j個廚師做第i道菜需要時間a[i][j],求做完所有菜,所有人等待的最小總時間。
思路:設所有的菜為sum。一個明顯的思路是將每個廚師拆成sum個點。然后sum個菜每個菜向每個廚師的每個點連邊,表示該道菜為該廚師第幾個做。由于這樣數據太大。動態加邊。每次增光一次后找到此次增廣的廚師,每道菜將其連邊。
?
struct node {int u,v,next,cost,cap; };node edges[N*5]; int head[N],e;void add(int u,int v,int cap,int cost) {e++;edges[e].u=u;edges[e].v=v;edges[e].cap=cap;edges[e].cost=cost;edges[e].next=head[u];head[u]=e; }void Add(int u,int v,int cap,int cost) {add(u,v,cap,cost);add(v,u,0,-cost); }int pre[N],F[N],C[N],visit[N];int SPFA(int s,int t,int n) {int i;for(i=0;i<=n;i++) F[i]=0,C[i]=INF,visit[i]=0;queue<int> Q;Q.push(s); F[s]=INF; C[s]=0;int u,v,cost,cap;while(!Q.empty()){u=Q.front();Q.pop();visit[u]=0;for(i=head[u];i;i=edges[i].next){if(edges[i].cap>0){v=edges[i].v;cost=edges[i].cost;cap=edges[i].cap;if(C[v]>C[u]+cost){C[v]=C[u]+cost;F[v]=min(F[u],cap);pre[v]=i;if(!visit[v]) visit[v]=1,Q.push(v);}}}}return F[t]; }int s,t,n,m,a[55][105],b[105],cnt[105],last[105];int main() {RD(n,m);int sum=0,i,j,x;FOR1(i,n) RD(b[i]),sum+=b[i];e=1;s=0; t=n+m+sum+1;FOR1(i,n) {Add(s,i,b[i],0);FOR1(j,m) {RD(a[i][j]);Add(i,n+j,1,a[i][j]);}}FOR1(i,m){cnt[i]=1;Add(n+i,t,1,0);last[i]=e;}int ans=0,temp;while(sum--){temp=SPFA(s,t,t);for(i=t;i!=s;i=edges[pre[i]].u){x=pre[i];ans+=temp*edges[x].cost;edges[x].cap-=temp;edges[x^1].cap+=temp;}for(j=1;j<=m&&edges[last[j]-1].cap;j++);cnt[j]++;FOR1(i,n) Add(i,n+m+sum,1,a[i][j]*cnt[j]);Add(n+m+sum,t,1,0);last[j]=e;}PR(ans); }?
?
?
總結
以上是生活随笔為你收集整理的BZOJ 2879 美食节(费用流-动态加边)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CC2540开发板学习笔记(一)——LE
- 下一篇: 数据库-锁的实践