zoukankan      html  css  js  c++  java
  • bzoj 1834 [ZJOI2010] network 网络扩容(费用流)

    题目描述

    给定一张有向图,每条边都有一个容量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

    题解

    话说其实不用新建图的……我看到好几位大佬的做法都是0.5倍经验+码量巨大的……

    实际上只要直接跑一个费用流就行了。对于第一问,我们直接连边,然后令费用为$0$,跑一遍,输出最大流即可

    对于第二问,只要在原来的每条边上再连一条边,容$inf$费为扩边费用,然后$k$的限制只要再建一个源点往$1$连容$k$费$0$的边。在残量网络上再跑一遍,输出最小费用即可

    考虑为什么这样做是对的。因为要跑最小费用最大流,而原图是无花费的最大流,那么只要在此残量网络上继续增广,就可以保证跑出最小费用了

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<queue>
     6 #define inf 0x3f3f3f3f
     7 using namespace std;
     8 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
     9 char buf[1<<21],*p1=buf,*p2=buf;
    10 inline int read(){
    11     #define num ch-'0'
    12     char ch;bool flag=0;int res;
    13     while(!isdigit(ch=getc()))
    14     (ch=='-')&&(flag=true);
    15     for(res=num;isdigit(ch=getc());res=res*10+num);
    16     (flag)&&(res=-res);
    17     #undef num
    18     return res;
    19 }
    20 const int N=1005,M=50005;
    21 struct node{
    22     int u,v,f,e;
    23     node(){}
    24     node(int u,int v,int f,int e):u(u),v(v),f(f),e(e){}
    25 }E[M];
    26 int ver[M],Next[M],head[N],edge[M],flow[M],tot=1;
    27 int dis[N],disf[N],vis[N],Pre[N],last[N];
    28 int n,m,k,s,t,maxflow,mincost;
    29 queue<int> q;
    30 inline void add(int u,int v,int f,int e){
    31     ver[++tot]=v,Next[tot]=head[u],head[u]=tot,flow[tot]=f,edge[tot]=e;
    32     ver[++tot]=u,Next[tot]=head[v],head[v]=tot,flow[tot]=0,edge[tot]=-e;
    33 }
    34 bool spfa(){
    35     memset(dis,0x3f,sizeof(dis));
    36     q.push(s),dis[s]=0,disf[s]=inf,Pre[t]=-1;
    37     while(!q.empty()){
    38         int u=q.front();q.pop();vis[u]=0;
    39         for(int i=head[u];i;i=Next[i]){
    40             int v=ver[i];
    41             if(flow[i]&&dis[v]>dis[u]+edge[i]){
    42                 dis[v]=dis[u]+edge[i],Pre[v]=u,last[v]=i;
    43                 disf[v]=min(disf[u],flow[i]);
    44                 if(!vis[v]) vis[v]=1,q.push(v);
    45             }
    46         }
    47     }
    48     return ~Pre[t];
    49 }
    50 void dinic(){
    51     while(spfa()){
    52         int u=t;maxflow+=disf[t],mincost+=disf[t]*dis[t];
    53         while(u!=s){
    54             flow[last[u]]-=disf[t];
    55             flow[last[u]^1]+=disf[t];
    56             u=Pre[u];
    57         }
    58     }
    59 }
    60 int main(){
    61     n=read(),m=read(),k=read();
    62     s=1,t=n;
    63     for(int i=1;i<=m;++i){
    64         int u=read(),v=read(),f=read(),e=read();
    65         E[i]=node(u,v,f,e);
    66         add(u,v,f,0);
    67     }
    68     dinic();
    69     printf("%d ",maxflow);
    70     for(int i=1;i<=m;++i){
    71         int u=E[i].u,v=E[i].v,e=E[i].e;
    72         add(u,v,inf,e);
    73     }
    74     s=0;
    75     add(s,1,k,0);
    76     dinic();
    77     printf("%d
    ",mincost);
    78     return 0;
    79 }
  • 相关阅读:
    海思HISI 3518EV200 AEC回音消除+ANR语音降噪(转)
    重磅消息 | 2020年最新全栈测试开发技能实战指南(第1期)
    推荐一款Python开源库,技术人必备的造数据神器!
    DevOps研发模式下「产品质量度量」方案实践
    自动化测试实战技巧:「用例失败重试机制」实现方案分享
    C#/VB.NET 在Word中添加条码、二维码
    Java 在PDF中绘制形状(基于Spire.Cloud.SDK for Java)
    Java 添加条码、二维码到Word文档
    Java 添加、下载、读取PDF附件信息(基于Spire.Cloud.SDK for Java)
    Java 添加、提取PDF中的图片
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9511172.html
Copyright © 2011-2022 走看看