【bzoj1834】 network 网络扩容 【ZJOI2010】

来源:互联网 发布:阿里巴巴一键铺货淘宝 编辑:程序博客网 时间:2024/05/17 21:53

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

这道题的第一问是最大流,用Dinic可以解决,第二问只要在第一问的残量网络再次加入原先的边,并将这些边的容量设为INF(实际上k就可以了),价格设为为c,同时将残量网络中的价格设为0,之后设置一个源点与1号相连,最后求一遍0-n的最小费用最大流就可以了,下面是程序:
#include<stdio.h>#include<string.h>#include<iostream>using namespace std;const int N=50005,INF=2139062143;struct queue{    int l,r,a[N];    void clear(){        l=0,r=1;    }    bool empty(){        return l+1==r;    }    int front(){        return a[(l+1)%N];    }    void pop(){        l=(l+1)%N;    }    void push(int x){        a[r]=x;        r=(r+1)%N;    }}q;struct edge{    int v,w,c,next;}a[N];int head[N],last[N],d[N],e[N],l=1;bool vis[N];void add(int u,int v,int w,int c){    l++;    a[l].v=v;    a[l].w=w;    a[l].c=c;    a[l].next=head[u];    head[u]=l;    l++;    a[l].v=u;    a[l].w=0;    a[l].c=-c;    a[l].next=head[v];    head[v]=l;}bool bfs(int s,int t){    memset(d,0,sizeof(d));    q.clear();    q.push(s);    d[s]=1;    while(!q.empty()){        int x=q.front();        q.pop();        int now=head[x];        while(now){            int &v=a[now].v;            if(!d[v]&&a[now].w){                d[v]=d[x]+1;                q.push(v);            }            now=a[now].next;        }    }    return d[t];}int dfs(int r,int low,int &t){    if(r==t||low==0){        return low;    }    int cost=0,i;    for(i=head[r];i;i=a[i].next){        int &v=a[i].v;        if(a[i].w&&d[r]+1==d[v]){            int tp=dfs(v,min(a[i].w,low-cost),t);            a[i].w-=tp;            a[i^1].w+=tp;            cost+=tp;            if(cost==low){                break;            }        }    }    return cost;}bool SPFA(int s,int t){    memset(d,0x7f,sizeof(d));    memset(vis,0,sizeof(vis));    q.clear();    q.push(s);    vis[s]=1;    d[s]=0;    while(!q.empty()){        int x=q.front();        q.pop();        vis[x]=0;        int now=head[x];        while(now){            int &v=a[now].v;            if(d[x]+a[now].c<d[v]&&a[now].w){                d[v]=d[x]+a[now].c;                last[v]=x;                e[v]=now;                if(!vis[v]){                    q.push(v);                    vis[v]=1;                }            }            now=a[now].next;        }    }    return d[t]<INF;}int main(){    int n,m,k,u,v,w,c,s=0,cost=0;    scanf("%d%d%d",&n,&m,&k);    while(m--){        scanf("%d%d%d%d",&u,&v,&w,&c);        add(u,v,w,c);    }    while(bfs(1,n)){        s+=dfs(1,INF,n);    }    printf("%d ",s);    w=l;    for(u=2;u<=w;u+=2){        add(a[u^1].v,a[u].v,k,a[u].c);        a[u].c=a[u^1].c=0;    }    add(0,1,k,0);    while(SPFA(0,n)){        int mn=k;        for(u=n;u;u=last[u]){            mn=min(mn,a[e[u]].w);        }        for(u=n;u;u=last[u]){            cost+=a[e[u]].c*mn;            a[e[u]].w-=mn;            a[e[u]^1].w+=mn;        }    }    printf("%d\n",cost);    return 0;}

原创粉丝点击