最小费用最大流板子

FZSZ Online Judge #707. 最小费用流

题目描述

这是一道模板题。

给定一个图,每条边有容量和费用,使用每条边的单位流量需要支付特定的费用。给定源点 1 和汇点 n,求图的最大流和最大流需要支付的最小费用。

输入格式

第一行两个整数 nm,表示有 n 个点 m 条边。

从第二行开始的之后 mm 行,每行四个整数 siticiwi 表示一条从 sisi 到 titi 的边,容量为 ci,单位流量需要支付的费用为 wi

输出格式

一行两个整数,分别表示最大流和最大流需要支付的最小费用。

样例

样例输入

8 23
2 3 2147483647 1
1 3 1 1
2 4 2147483647 2
1 4 1 2
2 8 2 0
3 5 2147483647 3
1 5 1 3
3 6 2147483647 4
1 6 1 4
3 8 2 0
3 2 2147483647 0
4 6 2147483647 5
1 6 1 5
4 7 2147483647 6
1 7 1 6
4 8 2 0
4 2 2147483647 0
5 8 0 0
5 2 2147483647 0
6 8 0 0
6 2 2147483647 0
7 8 0 0
7 2 2147483647 0

样例输出

6 24

数据范围与提示

1n400,0m15000,wi0,保证输入数据、中间结果以及答案在 32 位有符号整数范围内。

#include<iostream>
#include<cstdio>
#include<queue>
#define M 100000
#define INF 2147483647
#define re register
using namespace std;
queue<long long>q;
long long ans,n,m;
long long nxt[M+1],las[M+1],to[M+1],v[M+1],w[M+1],dis[M+1],inq[M+1],walk[M+1];
long long tot=1,t,S,T;
inline void add(long long x,long long y,long long _v,long _w){
    nxt[++tot]=las[x];
    las[x]=tot;
    to[tot]=y;
    v[tot]=_v;
    w[tot]=_w;
}
inline void adde(long long x,long long y,long long v,long long w){
    add(x,y,v,w);
    add(y,x,0,-w);
}
long long x,y,_w,_v;
inline long long bfs(){
    for(re long long i=0;i<=n;i++)
        inq[i]=walk[i]=0,dis[i]=(long long)INF*INF;
    q.push(S);
    dis[S]=0;
    inq[S]=1;
    long long now;
    while(!q.empty()){
        now=q.front();
        q.pop();
        inq[now]=0;
        for(re long long i=las[now];i;i=nxt[i])
            if(v[i]&&dis[to[i]]>dis[now]+w[i]){
                dis[to[i]]=dis[now]+w[i];
                if(!inq[to[i]]){
                    inq[to[i]]=1;
                    q.push(to[i]);
                }
            }
    }
    return dis[T]!=(long long)INF*INF?1:0;
}
inline long long dfs(long long now,long long f){
    if(now==T){
        ans+=(long long)dis[now]*f;
        return f;
    }
    long long d,ret=0;
    walk[now]=1;
    for(re long long i=las[now];i&&f;i=nxt[i])
        if(!walk[to[i]]&&v[i]&&dis[to[i]]==dis[now]+w[i]){
            d=dfs(to[i],v[i]<f?v[i]:f);
            f-=d;
            ret+=d;
            v[i]-=d;
            v[i^1]+=d;
        }
    walk[now]=0;
    if(!ret)
        dis[now]=-INF;
    return ret;
}
inline void dinic(){
    long long cnt=0;
    while(bfs())
        cnt+=dfs(S,INF);
    printf("%lld %lld\n",cnt,ans);
}
int main(){
    scanf("%lld%lld",&n,&m);
    S=1;
    T=n;
    for(re long long i=1;i<=m;i++){
        scanf("%lld%lld%lld%lld",&x,&y,&_w,&_v);
        adde(x,y,_w,_v);
    }
    dinic();
    return 0;
}

  

posted @ 2017-10-18 16:45  Stump  阅读(286)  评论(0编辑  收藏  举报