[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;
}

 

posted @ 2018-04-18 23:26  尹吴潇  阅读(107)  评论(0编辑  收藏  举报