zoukankan      html  css  js  c++  java
  • [BZOJ2879][NOI2012]美食节(费用流)

    设sm为所有p之和,套路地对每道菜建一个点,将每个厨师拆成sm个点,做的倒数第i道菜的代价为time*i。

    S向每道菜连边<0,p[i]>(前者为代价后者为流量),i菜到j厨师的第k个点连<v[i][j]*k,1>,厨师到T连<0,1>。

    但图太大了,于是动态加点。当厨师的第i个点被流完后再建第i+1个点,由于费用随i递增所以不会产生错误。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     4 #define For(i,x) for (int i=h[x],k; i; i=nxt[i])
     5 using namespace std;
     6 
     7 const int N=1000010,M=7000010,inf=1e9;
     8 int n,m,ans,S,T,cnt=1,sm,mn,v[50][120],p[50],h[N],d[N],pre[N],inq[N];
     9 int to[M],nxt[M],val[M],fl[M],q[M];
    10 
    11 void add(int u,int v,int c,int f){
    12     to[++cnt]=v; val[cnt]=c; fl[cnt]=f; nxt[cnt]=h[u]; h[u]=cnt;
    13     to[++cnt]=u; val[cnt]=-c; fl[cnt]=0; nxt[cnt]=h[v]; h[v]=cnt;
    14 }
    15 
    16 bool spfa(){
    17     rep(i,1,T) pre[i]=-1,inq[i]=0,d[i]=inf;
    18     d[S]=0; inq[S]=1; q[1]=S;
    19     for (int st=0,ed=1; st!=ed; ){
    20         int x=q[++st]; inq[x]=0;
    21         For(i,x) if (fl[i] && d[k=to[i]]>d[x]+val[i]){
    22             d[k]=d[x]+val[i]; pre[k]=i;
    23             if (!inq[k]) inq[k]=1,q[++ed]=k;
    24         }
    25     }
    26     return d[T]!=inf;
    27 }
    28 
    29 void mcmf(){
    30     for (ans=0; spfa(); ans+=d[T]*mn){
    31         mn=inf;
    32         for (int i=pre[T]; ~i; i=pre[to[i^1]]) mn=min(mn,fl[i]);
    33         for (int i=pre[T]; ~i; i=pre[to[i^1]]){
    34             fl[i]-=mn; fl[i^1]+=mn;
    35             if (to[i]==T && (to[i^1]-n)%sm){
    36                 int k=to[i^1]+1,x=(to[i^1]-n)/sm+1,y=(to[i^1]-n)%sm+1; add(k,T,0,1);
    37                 rep(j,1,n) add(j,k,v[j][x]*y,1);
    38             }
    39         }
    40     }
    41 }
    42 
    43 int main(){
    44     freopen("bzoj2879.in","r",stdin);
    45     freopen("bzoj2879.out","w",stdout);
    46     scanf("%d%d",&n,&m);
    47     rep(i,1,n) scanf("%d",&p[i]),sm+=p[i];
    48     rep(i,1,n) rep(j,1,m) scanf("%d",&v[i][j]);
    49     S=n+m*sm+1; T=S+1;
    50     rep(i,1,n) add(S,i,0,p[i]);
    51     rep(i,1,m) add(n+(i-1)*sm+1,T,0,1);
    52     rep(i,1,n) rep(j,1,m) add(i,n+(j-1)*sm+1,v[i][j],1);
    53     mcmf(); printf("%d
    ",ans);
    54     return 0;
    55 }
  • 相关阅读:
    从产品原型到交互设计的过渡——初学者心得
    谈什么是卡片式设计?
    vertical-align:middle的居中细节调整
    line-height:2和line-height:2em的区别,它们是有区别的
    css中!important的用法总结
    使用em为单位制作两列弹性布局
    如何动态修改下拉列表的默认选中项
    【转】深入浅出协议栈
    经典排序js实现
    js 数组的拷贝
  • 原文地址:https://www.cnblogs.com/HocRiser/p/10551507.html
Copyright © 2011-2022 走看看