[ZJOI2010]网络扩容

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

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

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


费用流板子题吧……建费用为0,流量为C的边,和费用为W,流量为inf的边,直接跑费用流即可

/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
template<typename T>T min(T x,T y){return x<y?x:y;}
template<typename T>T max(T x,T y){return x>y?x:y;}
inline char gc(){
    static char buf[1000000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>inline T frd(T x){
    int f=1; char ch=gc();
    for (;ch<'0'||ch>'9';ch=gc())   if (ch=='-')    f=-1;
    for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<1)+(x<<3)+ch-'0';
    return x*f;
}
template<typename T>inline T read(T x){
    int f=1;char ch=getchar();
    for (;ch<'0'||ch>'9';ch=getchar())  if (ch=='-')    f=-1;
    for (;ch>='0'&&ch<='9';ch=getchar())    x=(x<<1)+(x<<3)+ch-'0';
    return x*f;
}
inline void print(int x){
    if (x<0)    putchar('-'),x=-x;
    if (x>9)    print(x/10);
    putchar(x%10+'0');
}
const int N=1e3,M=2e4;
int pre[M+10],now[N+10],child[M+10],val[M+10],cost[M+10],tot=1;
int dis[N+10],deep[N+10],S,T;
void join(int x,int y,int v,int w){pre[++tot]=now[x],now[x]=tot,child[tot]=y,val[tot]=v,cost[tot]=w;}
void insert(int x,int y,int v,int w){join(x,y,v,w),join(y,x,0,-w);}
bool SPFA(){
    static int h[N+10];
    static bool vis[N+10];
    int head=0,tail=1;
    memset(dis,63,sizeof(dis));
    memset(deep,255,sizeof(deep));
    h[1]=S,dis[S]=0;
    while (head!=tail){
        if (++head>N)   head=1;
        int Now=h[head];
        for (int p=now[Now],son=child[p];p;p=pre[p],son=child[p]){
            if (val[p]&&dis[son]>dis[Now]+cost[p]){
                deep[son]=deep[Now]+1;
                dis[son]=dis[Now]+cost[p];
                if (!vis[son]){
                    if (++tail>N)   tail=1;
                    vis[h[tail]=son]=1;
                }
            }
        }
        vis[Now]=0;
    }
    return ~deep[T];
}
int Dinic(int x,int v){
    if (x==T)   return v;
    int res=0;
    for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
        if (val[p]&&dis[son]==dis[x]+cost[p]&&deep[son]>deep[x]){
            int k=Dinic(son,min(v,val[p]));
            v-=k,val[p]-=k;
            res+=k,val[p^1]+=k;
            if (!v) break;
        }
    }
    if (!res)   deep[x]=-1;
    return res;
}
void MCMF(int K){
    int MaxFlow=0,MinCost=0; bool put=0;
    while (SPFA()){
        if (dis[T]>0&&!put){
            printf("%d ",MaxFlow);
            put=1,MaxFlow=0;
        }
        int tmp=Dinic(S,inf);
        if (put&&K<=MaxFlow+tmp){
            MinCost+=(K-MaxFlow)*dis[T];
            printf("%d\n",MinCost);
            return;
        }
        MaxFlow+=tmp;
        MinCost+=tmp*dis[T];
    }
}
int main(){
    int n=read(0),m=read(0),K=read(0); S=1,T=n;
    for (int i=1;i<=m;i++){
        int x=read(0),y=read(0),v=read(0),w=read(0);
        insert(x,y,v,0);
        insert(x,y,inf,w);
    }
    MCMF(K);
    return 0;
}
posted @ 2019-03-30 21:13 Wolfycz 阅读(...) 评论(...) 编辑 收藏