zoukankan      html  css  js  c++  java
  • 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的答案。

    输入输出样例

    输入 #1
    5 8 2
    1 2 5 8
    2 5 9 9
    5 1 6 2
    5 1 1 8
    1 2 8 7
    2 5 4 9
    1 2 1 1
    1 4 2 1
    输出 #1
    13 19
    

    说明/提示

    30%的数据中,N<=100

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

    思路

    有点暴力。先跑一遍dinic,求出第一问的解,再重新建图,讲扩容记为容量inf,费用的边,最后新建t点,容量为maxflow+k,跑最大流最小费用,即可得到ans。

    代码

    #include<bits/stdc++.h>
    #define N 10700
    #define M 107000
    #define inf 1<<29
    using namespace std;
    struct node{
        int x,y,z,p,next;
    }e[M*2];
    int tot=1,head[N],maxflow=0,ans=0;
    int x[M],y[M],z[M],cost[M];
    int n,m,s,t,K;
    void add(int x,int y,int z,int p){
        e[++tot].y=y;e[tot].z=z;e[tot].p=p;e[tot].next=head[x];head[x]=tot;
        e[++tot].y=x;e[tot].z=0;e[tot].p=-p;e[tot].next=head[y];head[y]=tot;
    }
    int incf[N],v[N],pre[N],d[N];
    queue<int> q;
    bool bfs(){
        memset(d,0,sizeof(d));
        while(q.size()) q.pop();
        q.push(s);d[s]=1;
        while(q.size()){
            int x=q.front();q.pop();
            for(int i=head[x];i;i=e[i].next){
                int y=e[i].y,z=e[i].z;
                if(z&&!d[y]){
                    q.push(y);d[y]=d[x]+1;
                    if(y==t) return 1;
                }
            } 
        }
        return 0;
    }
    int dinic(int x,int flow){
        if(x==t) return flow;
        int rest=flow,k;
        for(int i=head[x];i;i=e[i].next){
            int y=e[i].y,z=e[i].z;
            if(z&&d[y]==d[x]+1){
                k=dinic(y,min(rest,z));
                if(!k) d[y]=0;
                e[i].z-=k;
                e[i^1].z+=k;
                rest-=k; 
            }
        }
        return flow-rest;
    }
    bool spfa(){
        queue<int> q;
        memset(d,0x3f,sizeof(d));// 0xcf
        memset(v,0,sizeof(v));
        q.push(s);d[s]=0;v[s]=1;
        incf[s]=inf;
        while(q.size()){
            int x=q.front();v[x]=0;q.pop();
            for(int i=head[x];i;i=e[i].next){
                int y=e[i].y,z=e[i].z;
                if(!z) continue;
                if(d[y]>d[x]+e[i].p){//d[y]<d[x]+e[i].p
                    d[y]=d[x]+e[i].p;
                    incf[y]=min(incf[x],z);
                    pre[y]=i;
                    if(!v[y]) v[y]=1,q.push(y);
                }
            }
        }
        if(d[t]==0x3f3f3f3f) return false;//0xcfcfcfcf
        return true;
    }
    void update(){
        int x=t;
        while(x!=s){
            int i=pre[x];
            e[i].z-=incf[t];
            e[i^1].z+=incf[t];
            x=e[i^1].y; 
        }
        maxflow+=incf[t];
        ans+=d[t]*incf[t];
    }
    void rebuild(){
        s=1;t=n+1;
        memset(head,0,sizeof(head));tot=1;
        for(int i=1;i<=m;i++){
            add(x[i],y[i],z[i],0);
            add(x[i],y[i],inf,cost[i]);
        }
        add(n,n+1,maxflow+K,0);
    }
    int main()
    {
        int flow=0;
        cin>>n>>m>>K;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d%d",&x[i],&y[i],&z[i],&cost[i]);
            add(x[i],y[i],z[i],0);
        } s=1;t=n;
        while(bfs()) 
            while(flow=dinic(s,inf)) maxflow+=flow;
        cout<<maxflow<<" ";
        rebuild();
        while(spfa()) update();
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    深入浅出了解OCR识别票据原理(Applying OCR Technology for Receipt Recognition)
    OCR技术浅探:基于深度学习和语言模型的印刷文字OCR系统
    Python 3.6.4 / win10 使用pip安装keras时遇到依赖的PyYAML安装出错
    简单http代理服务器搭建
    Socket之心跳包实现思路
    设计模式之访问者模式
    设计模式之责任链模式
    设计模式之策略者模式
    C#将.spl剥离成.emf文件格式
    设计模式之状态者模式
  • 原文地址:https://www.cnblogs.com/wangyiding2003/p/11551722.html
Copyright © 2011-2022 走看看