zoukankan      html  css  js  c++  java
  • [费用流]luogu P2050 美食节

    https://www.luogu.org/problemnew/show/P2050

    分析

    网络流的构图都好神仙啊%%%

    我们设i为第i个菜,从原点向i连流量为需求量的边

    然后动态加点,每次加入第j个城市倒数第k做第i个菜,其边权为k*t[j][i],流量均为一

    优化:只为每次增广后的那个厨师加点

    #include <iostream>
    #include <cstdio>
    #include <memory.h>
    #include <queue>
    using namespace std;
    struct Pipe {
        int v,c,w,nx;
    }g[10000010];
    int cnt=1,list[100050];
    int dis[100050],vis[100050],f[100050],nex[100050];
    int w[101][41];
    int n,m,s,t,ans,sum,l;
    
    void Add(int u,int v,int c,int w) {
        g[++cnt]=(Pipe){v,c,w,list[u]};list[u]=cnt;
        g[++cnt]=(Pipe){u,0,-w,list[v]};list[v]=cnt;
    }
    
    bool SPFA() {
        queue<int> q;
        while (!q.empty()) q.pop();
        memset(vis,0,sizeof vis);memset(dis,0x3f,sizeof dis);
        q.push(s);vis[s]=1;dis[s]=0;
        while (!q.empty()) {
            int u=q.front();q.pop();
            for (int i=list[u];i;i=g[i].nx)
                if (g[i].c&&dis[g[i].v]>dis[u]+g[i].w) {
                    dis[g[i].v]=dis[u]+g[i].w;f[g[i].v]=i;
                    if (!vis[g[i].v]) q.push(g[i].v);
                    vis[g[i].v]=1;
                }
            vis[u]=0;
        }
        return dis[t]!=0x3f3f3f3f;
    }
    
    void MCF() {
        int x=t,mf=2147483647;
        while (f[x]) {
            mf=min(mf,g[f[x]].c);
            x=g[f[x]^1].v;
        }
        x=t;ans+=dis[t];
        while (f[x]) {
            g[f[x]].c-=mf;g[f[x]^1].c+=mf;
            x=g[f[x]^1].v;
        }
    }
    
    void Dinic() {
        while (SPFA()) {
            MCF();
            int need=nex[g[f[t]^1].v];
            Add(need,t,1,0);
            for (int i=1;i<=n;i++) Add(i,need,1,((int)(need-n)/m+((need-n)%m!=0))*w[(need-n-1)%m+1][i]);
        }
    }
    
    int main() {
        scanf("%d%d",&n,&m);s=0;t=80049;
        for (int i=1,a;i<=n;i++) scanf("%d",&a),Add(s,i,a,0),sum+=a;
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++) scanf("%d",&w[j][i]),Add(i,n+j,1,w[j][i]);
        for (int i=1;i<=m;i++) Add(n+i,t,1,0);
        for (int i=1;i<=sum;i++)
            for (int j=1;j<=m;j++) nex[n+(i-1)*m+j]=n+i*m+j;
        Dinic();
        printf("%d",ans);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    (15)疯狂的程序员----《绝影》
    (14)嵌入式软件开发工程师技能要求总结
    (13)碎片化阅读只会让你变得越来越愚蠢
    (12)QT中搭建opencv开发环境
    (11)git服务器的安装和配置
    (10)python学习笔记一
    (3.3)狄泰软件学院C++课程学习剖析四
    (9)Linux下gdb调试学习
    (8)Linux(客户端)和Windows(服务端)下socket通信实例
    springMVC伪静态
  • 原文地址:https://www.cnblogs.com/mastervan/p/11149082.html
Copyright © 2011-2022 走看看