zoukankan      html  css  js  c++  java
  • NOI2012 美食节

    http://www.lydsy.com/JudgeOnline/problem.php?id=2879

    费用流。

    我们发现,每个厨师做的倒数第k道菜对总等待时间的贡献为k*做这道菜的时间。

    将每个厨师拆成P个点,第i个第表示这个厨师做倒数第i道菜。

    设Vi,j表示第i个厨师做第j道菜的点。

    Ui表示第i道菜。

    构图:

    S->Vi,j一条流量为1,费用为0的边;

    Vi,j->Uk一条流量为1,费用为j*t[k][i]的边;

    Ui->T一条流量为p[i],费用为0的边。

    但是数据范围比较大,我们可以动态加边。

    友情题:SDOI2007修车

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<fstream>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<utility>
    #include<set>
    #include<bitset>
    #include<vector>
    #include<functional>
    #include<deque>
    #include<cctype>
    #include<climits>
    #include<complex>
    //#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj
     
    using namespace std;
    
    typedef long long LL;
    typedef double DB;
    typedef pair<int,int> PII;
    typedef complex<DB> CP;
    
    #define mmst(a,v) memset(a,v,sizeof(a))
    #define mmcy(a,b) memcpy(a,b,sizeof(a))
    #define re(i,a,b)  for(i=a;i<=b;i++)
    #define red(i,a,b) for(i=a;i>=b;i--)
    #define fi first
    #define se second
    #define m_p(a,b) make_pair(a,b)
    #define SF scanf
    #define PF printf
    #define two(k) (1<<(k))
    
    template<class T>inline T sqr(T x){return x*x;}
    template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
    template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}
    
    const DB EPS=1e-9;
    inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;}
    const DB Pi=acos(-1.0);
    
    inline int gint()
      {
            int res=0;bool neg=0;char z;
            for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
            if(z==EOF)return 0;
            if(z=='-'){neg=1;z=getchar();}
            for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
            return (neg)?-res:res; 
        }
    inline LL gll()
      {
          LL res=0;bool neg=0;char z;
            for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
            if(z==EOF)return 0;
            if(z=='-'){neg=1;z=getchar();}
            for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
            return (neg)?-res:res; 
        }
    
    const int maxN=40;
    const int maxM=100;
    const int maxP=800;
    const int INF=1<<30;
    
    int N,M,P;
    int p[maxN+10];
    int t[maxN+10][maxM+10];
    int S,T,now,first[maxN+maxM*maxP+100];
    struct Tedge{int u,v,flow,cost,next;}edge[2*(maxN+maxN*maxM*maxP+maxP*maxM)+10000];
    
    inline void addedge(int u,int v,int flow,int cost)
      {
          now++;
          edge[now].u=u;
          edge[now].v=v;
          edge[now].flow=flow;
          edge[now].cost=cost;
          edge[now].next=first[u];
          first[u]=now;
      }
    inline void insert(int u,int v,int flow,int cost){addedge(u,v,flow,cost);addedge(v,u,0,-cost);}
    
    int head,tail,que[maxN+maxM*maxP+100];
    int vis[maxN+maxM*maxP+100],dis[maxN+maxM*maxP+100],fromedge[maxN+maxM*maxP+100];
    inline int SPFA()
      {
          int i;
          re(i,0,N+P*M+1)vis[i]=0,dis[i]=INF,fromedge[i]=-1;
          dis[que[0]=S]=0;
          head=0;tail=1;
          vis[S]=1;
          while(head!=tail)
            {
                int u=que[head++],v,flow,cost;if(head==T)head=0;
                vis[u]=0;
                for(i=first[u],v=edge[i].v,flow=edge[i].flow,cost=edge[i].cost;i!=-1;i=edge[i].next,v=edge[i].v,flow=edge[i].flow,cost=edge[i].cost)
                  if(flow>0 && dis[u]+cost<dis[v])
                    {
                        dis[v]=dis[u]+cost;
                        fromedge[v]=i;
                        if(!vis[v])
                                  {
                                      vis[que[tail]=v]=1;
                                      if(dis[que[tail]]<dis[que[head]])swap(que[head],que[tail]);
                                      tail++;if(tail==T)tail=0;
                                    }
                    }
            }
          return dis[T]!=INF;
      }
    inline void work(int &res)
      {
          int i,x=INF,y,a,b;
          for(i=fromedge[T];i!=-1;i=fromedge[edge[i].u])
              {
                  upmin(x,edge[i].flow);
                  if(edge[i].u==S)y=edge[i].v,a=(y-1)/P+1,b=y%P+1;
                }
          for(i=fromedge[T];i!=-1;i=fromedge[edge[i].u])edge[i].flow-=x,edge[i^1].flow+=x,res+=x*edge[i].cost;
          re(i,1,N)insert((a-1)*P+b,P*M+i,1,b*t[i][a]);
      }
    inline int mincostmaxflow()
      {
          int res=0;
            while(SPFA())work(res);
          return res;
      }
    
    int main()
      {
          freopen("delicacy.in","r",stdin);
          freopen("delicacy.out","w",stdout);
          int i,j;
          N=gint();M=gint();
          mmst(first,-1);now=-1;
          re(i,1,N)p[i]=gint(),P+=p[i];
            re(i,1,N)re(j,1,M)t[i][j]=gint();
            S=0;T=P*M+N+1;
          re(i,1,P*M)insert(S,i,1,0);
            re(i,1,N)insert(P*M+i,T,p[i],0);
            re(i,1,N)re(j,1,M)insert((j-1)*P+1,P*M+i,1,t[i][j]);
          cout<<mincostmaxflow()<<endl;
          return 0;
      }
    View Code
  • 相关阅读:
    Linux启动新进程的几种方法及比较[转]
    部署WEB应用的三种方式[转]
    HTML form label
    其他对象的表单
    Input对象2(貌似是独立标签)
    通过表单展示不一样的页面(input对象)
    神奇的表单
    有效地管理页面布局
    css新奇技术及其未来发展
    进一步讨论页面布局的方法
  • 原文地址:https://www.cnblogs.com/maijing/p/4693592.html
Copyright © 2011-2022 走看看