[NOI2012]美食节
题解:
很经典的网络流
对于每个厨师拆点分开统计 1倍 2倍 3倍
n(mp)^2 有点大
动态加边
即对于每个厨师有了i才会有i+1
不过好像还是有点卡常??
代码:
#include <bits/stdc++.h> using namespace std; #define INF 1e9 #define N 2000000 struct re{ int a,b,c,from,flow,cost; }a[N]; int head[N],l,d[N],p[N],aa[N],dy1[N],dy2[N],tt[1000][1000],cnt; int n,m,s,t,maxa[N]; bool inq[N]; void arr(int x,int y,int z,int flow,int cost,int xx,int yy) { a[++l].a=head[x]; a[l].b=y; a[l].c=z; head[x]=l; a[l].flow=flow; a[l].cost=cost; a[l].from=x; dy1[l]=xx; dy2[l]=yy; } bool bellmanford(int &flow,int &cost) { for (int i=1;i<=t;i++) d[i]=INF; memset(inq,0,sizeof(inq)); d[s]=0; inq[s]=1; p[s]=0; aa[s]=INF; queue<int> q; q.push(s); while (!q.empty()) { int x=q.front(); q.pop(); inq[x]=0; int u=head[x]; while (u) { int v=a[u].b; if (a[u].c>a[u].flow&&d[v]>d[x]+a[u].cost) { d[v]=d[x]+a[u].cost; p[v]=u; aa[v]=min(aa[x],a[u].c-a[u].flow); if (!inq[v]) q.push(v),inq[v]=1; } u=a[u].a; } } if (d[t]==INF) return(0); flow+=aa[t]; cost+=d[t]*aa[t]; int x=t; while (x!=s) { int u=p[x]; a[u].flow+=aa[t]; if (u%2) a[u+1].flow-=aa[t]; else a[u-1].flow-=aa[t]; if (dy2[u]==maxa[dy1[u]]) { int y=dy1[u]; maxa[y]++; cnt++; for (int i=1;i<=n;i++) { arr(i,cnt,1,0,tt[i][y]*maxa[y],y,maxa[y]); arr(cnt,i,0,0,-tt[i][y]*maxa[y],y,maxa[y]); } arr(cnt,t,1,0,0,0,0); arr(t,cnt,0,0,0,0,0); } //cout<<a[u].from<<" "<<a[u].b<<" "<<a[u].cost<<" "<<a[u].flow<<endl; x=a[u].from; } //cout<<endl; return 1; } int flow,cost; void mincost() { while (bellmanford(flow,cost)); } int pp[N]; int main() { std::ios::sync_with_stdio(false); cin>>n>>m; int sum=0; for (int i=1;i<=n;i++) { cin>>pp[i]; sum+=pp[i]; } for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) cin>>tt[i][j]; s=0; t=n+m*sum+1; for (int i=1;i<=n;i++) arr(s,i,pp[i],0,0,0,0),arr(i,s,0,0,0,0,0); maxa[0]=INF; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { maxa[j]=1; cnt=n+j; arr(i,cnt,1,0,tt[i][j],j,1); arr(cnt,i,0,0,-tt[i][j],j,1); } for (int i=1;i<=m;i++) { cnt=n+i; arr(cnt,t,1,0,0,0,0); arr(t,cnt,0,0,0,0,0); } cnt=n+m; /* for (int i=1;i<=l;i++) { cout<<a[i].b<<" "<<a[i].from<<" "<<a[i].c<<" "<<a[i].cost<<endl; } */ mincost(); cout<<cost<<endl; return 0; }