[BZOJ1834] [ZJOI2010]network 网络扩容

题目描述

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

题目分析

最大流+费用流
第一问直接最大流
第二问每条边的两个端点之间连费用
最后n向t连(k,0)的边

#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;
int n,m,k,s,t;
int head[1010],to[100000],net[100000],val[100000],flo[100000];
int tot=1;
int x[100000],y[100000],va[100000],vb[100000];
void add(int x,int y,int v,int c)
{
    net[++tot]=head[x],head[x]=tot,to[tot]=y,flo[tot]=v,val[tot]=c;
    net[++tot]=head[y];head[y]=tot,to[tot]=x,flo[tot]=0,val[tot]=-c;
}
int dis[1010],vis[1010];
int path[1010];
int bfs()
{
    queue<int>q;
    memset(dis,0,sizeof dis);
    q.push(s);
    dis[s]=1;
    while(q.size())
    {
        int nmp=q.front();
        q.pop();
        for(int i=head[nmp];i;i=net[i])
            if(flo[i]>0&&!dis[to[i]])
            {
                dis[to[i]]=dis[nmp]+1;
                q.push(to[i]);
                if(to[i]==t) return 1;
            }
    }
    return 0;
}
int dinic(int x,int flow)
{
    int tmp,temp=flow;
    if(x==t) return flow;
    for(int i=head[x];i;i=net[i])
        if(flo[i]>0&&dis[to[i]]==dis[x]+1)
        {
            tmp=dinic(to[i],min(flo[i],temp));
            if(tmp==0) dis[to[i]]=0;
            temp-=tmp,flo[i]-=tmp,flo[i^1]+=tmp;
            if(!temp) break;
        }
    return flow-temp;
}
int spfa()
{
    memset(dis,0x3f,sizeof dis);
    memset(vis,0,sizeof vis);
    queue<int>q;
    vis[s]=1,q.push(s),dis[s]=0;
    while(q.size())
    {
        int nmp=q.front();
        q.pop();
        vis[nmp]=0;
        for(int i=head[nmp];i;i=net[i])
            if(flo[i]>0&&dis[to[i]]>dis[nmp]+val[i])
            {
                dis[to[i]]=dis[nmp]+val[i];
                path[to[i]]=i^1;
                if(!vis[to[i]]) q.push(to[i]),vis[to[i]]=1;
            }
    }
    return dis[t]<0x3f3f3f3f;
}
int mincost()
{
    int sum=0;
    while(spfa())
    {
        int minflow=1<<30;
        for(int i=t;i!=1;i=to[path[i]]) minflow=min(minflow,flo[path[i]^1]);
        for(int i=t;i!=1;i=to[path[i]])
        {
            flo[path[i]]+=minflow;
            flo[path[i]^1]-=minflow;
            sum+=val[path[i]^1]*minflow;
        }
    }
    return sum;
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;i++)
        scanf("%d%d%d%d",&x[i],&y[i],&va[i],&vb[i]);
    for(int i=1;i<=m;i++) add(x[i],y[i],va[i],0);
    s=1,t=n;
    int ans=0;
    while(bfs()) ans+=dinic(s,1<<30);
    printf("%d ",ans);
    t=n+1;
    for(int i=1;i<=m;i++) add(x[i],y[i],1<<30,vb[i]);
    add(n,t,k,0);
    printf("%d",mincost());
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注