1. 程式人生 > >洛谷2050 BZOJ2897美食節題解

洛谷2050 BZOJ2897美食節題解

tdi cos zoj min math amp print 拆點 mes

放個鏈接

BZ鏈接

其實這題就是修車的加強版,做法差不多,還是對於每個廚師進行拆點

可是這樣強行建圖跑網絡流會T飛

我們發現,如果一個廚師沒有做倒數第x到菜,他一定不會做倒數第x+1到菜

我們的每次增廣表示有廚師的倒數第k道菜做了y,這樣我們把這位廚師的倒數做k+1道菜的邊連起來

動態加邊

連邊是註意每個點的意思是什麽

# include<iostream>
# include<cstdio>
# include<algorithm>
# include<cmath>
# include<cstring>
# include
<queue> using namespace std; const int inf = 0x3f3f3f3f; const int mn = 100005; int c[45][105],p[45]; struct edge{int to,next,flow,cost;}; edge e[3000005]; int head[mn],edge_max=1; void add(int x,int y,int z,int k) { //printf("%d %d %d %d\n",x,y,z,k); e[++edge_max].to=y; e[edge_max].flow
=z; e[edge_max].cost=k; e[edge_max].next=head[x]; head[x]=edge_max; } int n,m,sum; int dis[mn],pe[mn],pv[mn],ansc,ansf; bool vis[mn]; queue<int> q; bool spfa(int x,int y) { memset(dis,0x3f,sizeof(dis)); dis[x]=0; q.push(x); while(!q.empty()) {
int u=q.front(); vis[u]=0; q.pop(); for(int i=head[u];i;i=e[i].next) { if(e[i].flow>0 && e[i].cost+dis[u]<dis[e[i].to]) { dis[e[i].to]=dis[u]+e[i].cost; pv[e[i].to]=u; pe[e[i].to]=i; if(!vis[e[i].to]) { vis[e[i].to]=1; q.push(e[i].to); } } } } //for(int i=0;i<=y;i++) //printf("%d ",dis[y]); return dis[y]<inf; } void max_flow(int x,int y) { int kflow,a,b;//a表示廚師編號 while(spfa(x,y)) { //printf("%d %d\n",ansc,ansf); kflow=inf; for(int i=y;i!=x;i=pv[i]) kflow=min(kflow,e[pe[i]].flow); a=(pv[y]-1)/sum+1; b=pv[y]%sum+1; ansf+=kflow; ansc+=kflow*dis[y]; for(int i=y;i!=x;i=pv[i]) { e[pe[i]].flow-=kflow; e[pe[i]^1].flow+=kflow; //ansc+=kflow*e[pe[i]].cost; } for(int i=1;i<=n;i++) add(i+m*sum,(a-1)*sum+b,1,c[i][a]*b),add((a-1)*sum+b,i+m*sum,0,-c[i][a]*b); } } int main() { int st=0; //freopen("testdata.in","r",stdin); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&p[i]),sum+=p[i]; int en=sum*m+n+1; // printf("%d\n",en); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&c[i][j]); for(int i=1;i<=n;i++) add(st,i+m*sum,p[i],0),add(i+m*sum,st,0,0); for(int i=1;i<=m*sum;i++) add(i,en,1,0),add(en,i,0,0); for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) add(j+m*sum,(i-1)*sum+1,1,c[j][i]),add((i-1)*sum+1,j+m*sum,0,-c[j][i]); max_flow(st,en); printf("%d",ansc); return 0; }

洛谷2050 BZOJ2897美食節題解