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

    思路

    神奇的网络流优化
    这题相当于修车的数据加强版XD
    依然是用点表示第i个厨师倒数第j个做某个菜,贡献就是会使之后的人都加上这个菜的等待时间
    然后这样有60pts
    考虑优化,发现每次只可能是某一个厨师做一道菜,所以每次只给上次做菜的那个厨师加一层边就好了
    然后我常数太大只能在luogu上吸氧

    代码

    // luogu-judger-enable-o2
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <queue>
    using namespace std;
    const int MAXN = 700000;
    const int INF = 0x3f3f3f3f;
    struct Edge{
        int u,v,cap,cost,flow;
    };
    vector<Edge> edges;
    vector<int> G[MAXN];
    void addedge(int u,int v,int cap,int cost){
        edges.push_back((Edge){u,v,cap,cost,0});
        edges.push_back((Edge){v,u,0,-cost,0});
        int cnt=edges.size();
        G[u].push_back(cnt-2);
        G[v].push_back(cnt-1);
    }
    queue<int> q;
    int s,t,a[MAXN],d[MAXN],p[MAXN],vis[MAXN];
    bool spfa(int &flow,int &cost){
        memset(d,0x3f,sizeof(d));
        memset(p,0,sizeof(p));
        q.push(s);
        vis[s]=true;
        a[s]=INF;
        d[s]=0;
        while(!q.empty()){
            int x=q.front();
            q.pop();
            vis[x]=false;
            for(int i=0;i<G[x].size();i++){
                Edge &e = edges[G[x][i]];
                if(e.cap>e.flow&&d[x]+e.cost<d[e.v]){
                    d[e.v]=d[x]+e.cost;
                    a[e.v]=min(a[x],e.cap-e.flow);
                    p[e.v]=G[x][i];
                    if(!vis[e.v]){
                        vis[e.v]=true;
                        q.push(e.v);
                    }
                }
            }
        }
        if(d[t]==INF)
            return false;
        flow+=a[t];
        cost+=d[t]*a[t];
        for(int i=t;i!=s;i=edges[p[i]].u){
            edges[p[i]].flow+=a[t];
            edges[p[i]^1].flow-=a[t];
        }
        return true;
    }
    int n,m,sum,val[50][120],who[MAXN],num[MAXN];
    void MCMF(int &cost,int &flow){
        cost=0,flow=0;
        while(spfa(flow,cost)){
            int mid=edges[p[t]].u;
            int times=num[mid-1];
            int tmid=who[mid];
            addedge(mid-1,t,1,0);
            for(int i=1;i<=n;i++)
                addedge(i,mid-1,INF,(sum-times+1)*val[i][tmid]);
        }
    }
    int main(){
        //freopen("testdata.in","r",stdin);
        scanf("%d %d",&n,&m);
        s=MAXN-2;
        t=MAXN-3;
        for(int i=1;i<=n;i++){
            int mid;
            scanf("%d",&mid);
            sum+=mid;
            addedge(s,i,mid,0);
            who[i]=i;
        }
        for(int i=1;i<=m;i++){
          for(int j=1;j<=sum;j++){
                who[(i-1)*sum+j+n]=i;
                num[(i-1)*sum+j+n]=j;
          }
        }
        for(int i=1;i<=m;i++)
            addedge(i*sum+n,t,1,0);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d",&val[i][j]);
                addedge(i,j*sum+n,INF,val[i][j]);
            }
        }
        //printf("ok
    ");
        int cost,flow;
        MCMF(cost,flow);
        //printf("ok
    ");
        printf("%d
    ",cost);
        return 0;
    }
    
    
  • 相关阅读:
    2018 ACM 网络选拔赛 徐州赛区
    2018 ACM 网络选拔赛 焦作赛区
    2018 ACM 网络选拔赛 沈阳赛区
    poj 2289 网络流 and 二分查找
    poj 2446 二分图最大匹配
    poj 1469 二分图最大匹配
    poj 3249 拓扑排序 and 动态规划
    poj 3687 拓扑排序
    poj 2585 拓扑排序
    poj 1094 拓扑排序
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10494075.html
Copyright © 2011-2022 走看看