洛谷 P3381 【模板】最小费用最大流

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
const int inf = 0x3f3f3f3f;
struct node{
    int v, w, nxt, f;
}edge[N];
int n, m, st, ed, cnt, mc, mf;
int fir[N], dis[N], fl[N], fa[N];
//dis[N] 费用的最短距离
//fl[N]  最短路径上的最小流量
//fa[N]  记录最短路径
bool vis[N];
inline void add(int u, int v, int w, int f){
    edge[++cnt] = (node){v, w, fir[u], f}; fir[u] = cnt;
    edge[++cnt] = (node){u, 0, fir[v], -f}; fir[v] = cnt;
}
inline int spfa(){
    memset(vis, false, sizeof(vis));
    vis[st] = true;
    memset(dis, 0x3f3f3f3f, sizeof(dis));
    dis[st] = 0;
    queue<int> q;
    q.push(st);
    fl[st] = inf;
    while(!q.empty()){
        int u = q.front();
        q.pop();
        vis[u] = false;
        for(int i = fir[u]; i; i = edge[i].nxt){
            int v = edge[i].v;
            if(edge[i].w && dis[v] > dis[u] + edge[i].f){
                dis[v] = dis[u] + edge[i].f;
                fl[v] = min(fl[u], edge[i].w);
                fa[v] = i;
                if(!vis[v]){
                    vis[v] = true;
                    q.push(v);
                }
            }
        }
    }
    return dis[ed] != inf;
}
inline void MCMF(){
    while(spfa()){
        int x = ed;
        mf += fl[ed];
        mc += fl[ed] * dis[ed];
        while(x != st){
            int i = fa[x];
            edge[i].w -= fl[ed];
            edge[i^1].w += fl[ed];
            x = edge[i^1].v;
        }
    }
}
int main(){
#ifdef ONLINE_JUDGE
#else
    freopen("in.txt", "r", stdin);
#endif //ONLINE_JUDGE
    int a, b, c, d;
    cnt = 1;
    mc = 0, mf = 0;
    memset(fir, 0, sizeof(fir));
    scanf("%d%d%d%d", &n, &m, &st, &ed);
    for(int i = 1; i <= m; i++){
        scanf("%d%d%d%d", &a, &b, &c, &d);
        add(a, b, c, d);
    }
    MCMF();
    printf("%d %d\n", mf, mc);
    return 0;
}

posted on 2019-02-27 16:34  坤sir  阅读(151)  评论(0编辑  收藏  举报

导航