【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 }