[BZOJ1497]&&[ZJOI2010] network 网络扩容

描述 Description

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

输入格式 InputFormat

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

输出格式 OutputFormat

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

样例输入 SampleInput

10 20 5
1 7 38 58
7 4 62 61
4 10 50 61
10 5 39 65
9 1 21 45
7 9 76 30
8 7 28 20
9 6 41 2
8 9 12 54
7 5 91 75
3 4 16 22
5 1 33 47
2 3 63 86
1 3 63 95
9 3 33 82
8 10 45 87
6 8 75 19
8 4 49 75
8 1 83 71
8 5 33 69

样例输出 SampleOutput

54 110


BZOJ 1834


原流量零费用建边最大流,然后在残余网络基础上原费用无限流量建边费用流。

#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
const int inf=0x7fffffff/27.11;
const int maxn=2005;
const int maxm=10005;
int i,j,t,n,m,l,r,k,z,y,x;
struct edge
{
    int to,fl,co,nx;
}e[2*maxm];
struct ed
{
    int fr,to,fl,co;
}a[maxm];
int head[maxn],dis[maxn],used[maxn],cur[maxn],pre[maxn],flow[maxn];
int cnt,num;
deque <int> q;
inline void read(int &x)
{
    x=0;char ch=getchar();
    while (ch<'0' || ch>'9') ch=getchar();
    while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
}
inline void ins(int u,int v,int f,int w)
{
    e[num++]=((edge){v,f,w,head[u]});head[u]=num-1;
    e[num++]=((edge){u,0,-w,head[v]});head[v]=num-1;
}
inline bool bfs(int s,int t,int tim)
{
    int i,u,v,w;
    while (!q.empty()) q.pop_front();
    dis[s]=0;used[s]=tim;
    q.push_back(s);
    while (!q.empty())
    {
        u=q.front();q.pop_front();
        for (i=head[u];i!=-1;i=e[i].nx)
        {
            v=e[i].to;
            if (used[v]!=tim && e[i].fl>0)
            {
                used[v]=tim;
                dis[v]=dis[u]+1;
                q.push_back(v);
            }
        }
    }
    return (used[t]==tim);
}
int dfs(int u,int t,int flow)
{
    int i,j,v,w,d,k;
    if (u==t) return flow;
    d=flow;
    for (i=cur[u];i!=-1;i=e[i].nx)
    {
        v=e[i].to;
        if (dis[v]==dis[u]+1 && e[i].fl>0)
        {
            k=dfs(v,t,min(d,e[i].fl));
            e[i].fl-=k;e[i^1].fl+=k;d-=k;
            if (d==0) break;
        }
    }
    return flow-d;
}
inline void dinic(int s,int t)
{
    int i,j,ans=0;
    while (bfs(s,t,++cnt))
    {
        memcpy(cur,head,sizeof(head));
        ans+=dfs(s,t,inf);
    }
    printf("%d",ans);
}
inline bool spfa(int s,int t,int tim)
{
    int i,j,u,v,w;
    while (!q.empty()) q.pop_front();
    for (i=s;i<=t;i++) dis[i]=inf;
    pre[s]=-1;flow[s]=inf;
    q.push_back(s);used[s]=tim;dis[s]=0;
    while (!q.empty())
    {
        u=q.front();q.pop_front();used[u]=tim-1;
        for (i=head[u];i!=-1;i=e[i].nx)
        {
            v=e[i].to;
            if (dis[v]>dis[u]+e[i].co && e[i].fl>0)
            {
                dis[v]=dis[u]+e[i].co;
                pre[v]=i;
                flow[v]=min(flow[u],e[i].fl);
                if (used[v]!=tim)
                {
                    used[v]=tim;
                    if (!q.empty() && dis[v]<q.front()) q.push_front(v);
                    else q.push_back(v);
                }
            }
        }
    }
    return (dis[t]!=inf);
}
void inline mcmf(int s,int t)
{
    int i,j,ans=0,k;
    while (spfa(s,t,++cnt))
    {
        ans+=flow[t]*dis[t];
        for (i=pre[t];i!=-1;i=pre[e[i^1].to]) e[i].fl-=flow[t],e[i^1].fl+=flow[t];
    }
    printf("%d\n",ans);
}
int main()
{
    cnt=num=0;
    read(n);read(m);read(k);
    for (i=0;i<=n;i++) head[i]=-1;
    for (i=1;i<=m;i++) read(a[i].fr),read(a[i].to),read(a[i].fl),read(a[i].co),ins(a[i].fr,a[i].to,a[i].fl,0);
    dinic(1,n);
    for (i=1;i<=m;i++) ins(a[i].fr,a[i].to,inf,a[i].co);
    ins(0,1,k,0);
    mcmf(0,n);
    return 0;
}