洛谷2050 BZOJ2897美食节题解
其实这题就是修车的加强版,做法差不多,还是对于每个厨师进行拆点
可是这样强行建图跑网络流会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; }