• 洛谷 P2604 [ZJOI2010]网络扩容 解题报告


    P2604 [ZJOI2010]网络扩容

    题目描述

    给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求: 1、 在不扩容的情况下,1到N的最大流; 2、 将1到N的最大流增加K所需的最小扩容费用。

    输入输出格式

    输入格式:

    输入文件的第一行包含三个整数N,M,K,表示有向图的点数、边数以及所需要增加的流量。 接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边。

    输出格式:

    输出文件一行包含两个整数,分别表示问题1和问题2的答案。

    说明

    30%的数据中,N<=100

    100%的数据中,N<=1000,M<=5000,K<=10


    k这么小,开始以为是分层图搞事呢。

    第一问裸的最大流。

    第二问我们对初始的每条边新建一条费用边,容量为inf,表示随便用,单位费用就连初始费用,表示要花钱。

    保证增加的流量为k,我们搞一个超级源点容量为k连原源点1。

    在跑完最大流之后的残余网络上跑最小费用最大流。

    之前对最大流求法中的反悔理解的不深刻,在写这个题的时候一直觉得直接跑残量网络失去了对原来最大流的反悔机会。但实际上,基于路径交换的反悔原理,直接跑残量网络是没问题的。

    代码里面偷了懒,万一有免费的边就错了


    Code:

    #include <cstdio>
    #include <cstring>
    #include <queue>
    using namespace std;
    const int N=1010;
    const int M=10010;
    const int inf=0x3f3f3f3f;
    int head[N],edge[M<<1],cost[M<<1],to[M<<1],Next[M<<1],cnt=1;
    void add(int u,int v,int w,int c)
    {
        edge[++cnt]=w;cost[cnt]=c;Next[cnt]=head[u];to[cnt]=v;head[u]=cnt;
        edge[++cnt]=0;cost[cnt]=-c;Next[cnt]=head[v];to[cnt]=u;head[v]=cnt;
    }
    int maxflow,n,m,k;
    int dep[N];
    bool bfs()
    {
        memset(dep,0,sizeof(dep));
        dep[1]=1;
        queue <int > q;
        q.push(1);
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=head[u];i;i=Next[i])
            {
                int v=to[i];
                if(!cost[i]&&!dep[v]&&edge[i])
                {
                    dep[v]=dep[u]+1;
                    if(v==n) return 1;
                    q.push(v);
                }
            }
        }
        return 0;
    }
    int dfs(int now,int flow)
    {
        if(now==n) return flow;
        int rest=flow,k;
        for(int i=head[now];i&&rest;i=Next[i])
        {
            int v=to[i];
            if(!cost[i]&&edge[i]&&dep[v]==dep[now]+1)
            {
                k=dfs(v,min(rest,edge[i]));
                if(!k) dep[v]=0;
                rest-=k;
                edge[i]-=k;
                edge[i^1]+=k;
            }
        }
        return flow-rest;
    }
    void Dinic()
    {
        int flow=0;
        while(bfs())
            while(flow=dfs(1,inf)) maxflow+=flow;
        printf("%d ",maxflow);
    }
    int pre[N],used[N],dis[N];
    int spfa()
    {
        queue <int > q;
        q.push(0);
        memset(dis,0x3f,sizeof(dis));
        dis[0]=0;
        while(!q.empty())
        {
            int u=q.front();
            used[u]=0;
            q.pop();
            for(int i=head[u];i;i=Next[i])
            {
                int v=to[i];
                if(edge[i]&&dis[v]>dis[u]+cost[i])
                {
                    dis[v]=dis[u]+cost[i];
                    pre[v]=i;
                    if(!used[v])
                        used[v]=1,q.push(v);
                }
            }
        }
        return dis[n]!=inf;
    }
    void costflow()
    {
        int ans=0;
        while(spfa())
        {
            int mi=inf;
            for(int now=n;now;now=to[pre[now]^1])
                mi=min(edge[pre[now]],mi);
            ans+=dis[n]*mi;
            for(int now=n;now;now=to[pre[now]^1])
                edge[pre[now]]-=mi,edge[pre[now]^1]+=mi;
        }
        printf("%d
    ",ans);
    }
    void init()
    {
        scanf("%d%d%d",&n,&m,&k);
        int u,v,w,c;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d%d",&u,&v,&w,&c);
            add(u,v,w,0),add(u,v,inf,c);
        }
    }
    void work()
    {
        Dinic();
        add(0,1,k,0);
        costflow();
    }
    int main()
    {
        init();
        work();
        return 0;
    }
    
    

    2018.7.14

  • 相关阅读:
    Eclipse Class Decompiler——Java反编译插件
    HttpServletRequest对象方法的用法
    Java构造和解析Json数据的两种方法详解一
    sql索引的填充因子多少最好,填充因子有什么用
    JSON格式的String 怎么转成 net.sf.json.JSONObject
    Highcharts使用指南
    定时自动执行SQL存储过程(图文详解)
    cxf wsdl2java环境变量设置与使用
    使用 Chrome 开发者工具进行 JavaScript 问题定位与调试
    Java调用webservice接口方法
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9308891.html
Copyright © 2020-2023  润新知