【BZOJ】【2879】【NOI2012】美食节

网络流/费用流


  跟 BZOJ 1070 修车 几乎是一道题,只是这题“要修的车”(即菜)多了很多……几乎是从$n$变成了$n^2$,所以建图的时候就得动态加点……

  也就是说,当一个厨师已经确定了他的后k道菜的时候,再加入表示倒数第k+1道菜的节点。

  我个xx一开始写成了每次加一层……不 T 才怪……

  加点过程看min_cost_flow(即mcf)这个函数吧,每次通过找流过来的节点,来确定要加的点。

  1 /**************************************************************
  2     Problem: 2879
  3     User: Tunix
  4     Language: C++
  5     Result: Accepted
  6     Time:7416 ms
  7     Memory:72872 kb
  8 ****************************************************************/
  9  
 10 //BZOJ 2879
 11 #include<cmath>
 12 #include<vector>
 13 #include<cstdio>
 14 #include<cstring>
 15 #include<cstdlib>
 16 #include<iostream>
 17 #include<algorithm>
 18 #define rep(i,n) for(int i=0;i<n;++i)
 19 #define F(i,j,n) for(int i=j;i<=n;++i)
 20 #define D(i,j,n) for(int i=j;i>=n;--i)
 21 #define pb push_back
 22 #define CC(a,b) memset(a,b,sizeof(a))
 23 using namespace std;
 24 int getint(){
 25     int v=0,sign=1; char ch=getchar();
 26     while(!isdigit(ch)) {if(ch=='-') sign=-1; ch=getchar();}
 27     while(isdigit(ch))  {v=v*10+ch-'0'; ch=getchar();}
 28     return v*sign;
 29 }
 30 const int N=100000,M=3000000,INF=~0u>>2;
 31 const double eps=1e-8;
 32 /*******************template********************/
 33 int n,m,ans,tot,tim[41][101],p[41];
 34 struct edge{int from,to,v,c;};
 35 struct Net{
 36     edge E[M];
 37     int head[N],next[M],cnt;
 38     void ins(int x,int y,int z,int c){
 39         E[++cnt]=(edge){x,y,z,c};
 40         next[cnt]=head[x]; head[x]=cnt;
 41     }
 42     void add(int x,int y,int z,int c){
 43         ins(x,y,z,c); ins(y,x,0,-c);
 44     }
 45     int from[N],Q[M],d[N],S,T,ed;
 46     bool inq[N],sign;
 47     bool spfa(){
 48         int l=0,r=-1;
 49         F(i,1,T) d[i]=INF;
 50         d[S]=0; Q[++r]=S; inq[S]=1;
 51         while(l<=r){
 52             int x=Q[l++];
 53             inq[x]=0;
 54             for(int i=head[x];i;i=next[i])
 55                 if(E[i].v>0 && d[x]+E[i].c<d[E[i].to]){
 56                     d[E[i].to]=d[x]+E[i].c;
 57                     from[E[i].to]=i;
 58                     if (!inq[E[i].to]){
 59                         Q[++r]=E[i].to;
 60                         inq[E[i].to]=1;
 61                     }
 62                 }
 63         }
 64         return d[T]!=INF;
 65     }
 66     void mcf(){
 67         int x=INF,a,b;
 68         for(int i=from[T];i;i=from[E[i].from]){
 69             x=min(x,E[i].v);
 70             if (E[i].to==T){
 71                 a=E[i].from%tot+1;
 72                 b=(E[i].from-1)/tot;
 73             }
 74         }
 75         for(int i=from[T];i;i=from[E[i].from]){
 76             E[i].v-=x;
 77             E[i^1].v+=x;
 78         }
 79         ans+=x*d[T];
 80         if (a!=1)
 81             F(i,1,n)
 82                 add(i,b*tot+a,1,a*tim[i][b]);
 83     }
 84     void init(){
 85         n=getint(); m=getint(); cnt=ed=1; tot=0;
 86         F(i,1,n) {p[i]=getint(); tot+=p[i];}
 87         S=0; T=tot+tot*m+1;
 88         F(i,1,n) F(j,1,m) tim[i][j]=getint();
 89         F(i,1,n) add(S,i,p[i],0);
 90         F(i,tot+1,tot+tot*m) add(i,T,1,0);
 91         F(i,1,n)
 92             F(j,1,m)
 93                 add(i,j*tot+1,1,tim[i][j]);
 94         ans=0;
 95         while(spfa()) mcf();
 96         printf("%d\n",ans);
 97     }
 98 }G1;
 99 int main(){
100 #ifndef ONLINE_JUDGE
101     freopen("2879.in","r",stdin);
102     freopen("2879.out","w",stdout);
103 #endif
104     G1.init();
105     return 0;
106 }
View Code

 

posted @ 2015-03-18 16:37  Tunix  阅读(202)  评论(0编辑  收藏  举报