bzoj1834 网络扩容

Description

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

Input

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

Output

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

Sample Input

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

Sample Output

13 19
30%的数据中,N<=100
100%的数据中,N<=1000,M<=5000,K<=10
 
无聊的最大流+费用流
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=1000+10,maxm=3*5000+10,INF=0x3f3f3f3f;
int n,m,k,tu[maxn],S,T;
 
int aa,bb;char cc;
int read() {
    aa=0;cc=getchar();bb=1;
    while(cc<'0'||cc>'9') {
        if(cc=='-') bb=-1;
        cc=getchar();
    }
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    return aa*bb;
}
 
struct Node{
    int x,y,cap,flow,w;
    Node(){}
    Node(int x,int y,int cap,int w) :x(x),y(y),cap(cap),w(w){}
}node[2*maxm];
 
int cur[maxn],fir[maxn],nxt[2*maxm],e=1;
void add(int x,int y,int z,int w) {
    node[++e]=Node(x,y,z,w); nxt[e]=fir[x];fir[x]=e;
    node[++e]=Node(y,x,0,-w); nxt[e]=fir[y];fir[y]=e;
}
 
int zz[maxn],from[maxn],dis[maxn];bool vis[maxn];
bool spfa() {
    int s=1,t=0,x,y,z;
    memset(dis,0x3f3f3f3f,sizeof(dis));
    memset(zz,0,sizeof(zz));
    memset(vis,0,sizeof(vis));
    zz[++t]=S;vis[S]=1;dis[S]=0;
    while(s<=t) {
        x=zz[s%maxn];
        for(y=fir[x];y;y=nxt[y]) {
            z=node[y].y;
            if(dis[z]<=dis[x]+node[y].w||node[y].flow>=node[y].cap) continue;
            if(!vis[z]) {
                t++; zz[t%maxn]=z;
                vis[z]=1;
            }
            from[z]=y;
            dis[z]=dis[x]+node[y].w;
        }
        vis[x]=0;s++;
    }
    return dis[T]!=INF;
}
 
int MCMF() {
    int rs=0,now=k;
    while(spfa()&&k) {
        now=k;
        for(int i=T;i!=S;i=node[from[i]].x) now=min(now,node[from[i]].cap-node[from[i]].flow);
        now=min(now,k);k-=now;
        for(int i=T;i!=S;i=node[from[i]].x) {
            node[from[i]].flow+=now;
            node[from[i]^1].flow-=now;
            rs+=now*node[from[i]].w;
        }
    }
    return rs;
}

bool BFS() {
    int s=1,t=0,x,y,z;
    memset(dis,-1,sizeof(dis));
    dis[S]=0;zz[++t]=S;
    while(s<=t) {
        x=zz[s];s++;
        for(y=fir[x];y;y=nxt[y]) {
            z=node[y].y;
            if(dis[z]!=-1||node[y].flow>=node[y].cap) continue;
            zz[++t]=z; dis[z]=dis[x]+1;
        }
    }
    return dis[T]!=-1;
}
  
int DFS(int pos,int maxf) {
    if(pos==T||!maxf) return maxf;
    int rs=0,now,z;
    for(int &y=cur[pos];y;y=nxt[y]) {
        z=node[y].y;
        if(dis[z]!=dis[pos]+1||node[y].flow>=node[y].cap) continue;
        now=DFS(z,min(maxf,node[y].cap-node[y].flow));
        rs+=now;maxf-=now;
        node[y].flow+=now;
        node[y^1].flow-=now;
    }
    if(!rs) dis[pos]=-1;
    return rs;
}
  
int dinic() {
    int re=0;
    while(BFS()) {
        memcpy(cur,fir,sizeof(fir));
        re+=DFS(S,INF);
    }
    return re;
}
 
int ff[3*maxm],ff_tot=0;
 
int main() {
    n=read();m=read();k=read();
    int x,y,z,w;S=1;T=n;
    for(int i=1;i<=m;++i) {
        x=read();y=read();z=read();w=read();
        add(x,y,z,0);
        ff[3*ff_tot+1]=x;ff[3*ff_tot+2]=y;ff[3*(++ff_tot)]=w;
    }
    printf("%d ",dinic());
    for(int i=1;i<=ff_tot;++i) add(ff[i*3-2],ff[i*3-1],INF,ff[i*3]);
    printf("%d",MCMF());
    return 0;
}

模板拼接

转载于:https://www.cnblogs.com/Serene-shixinyi/p/7445510.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值