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

题目描述

如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。

输入输出格式

输入格式:
第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。

接下来M行每行包含四个正整数ui、vi、wi、fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi。

输出格式:
一行,包含两个整数,依次为最大流量和在最大流量情况下的最小费用。

代码

#include<queue>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
const int maxn=1005,maxm=5e5+5,INF=0x3f3f3f3f;
deque <int> Q;
int N,M,S,T,MF,MC;
int dis[maxn],vis[maxn];
int son[maxm],flw[maxm],cst[maxm],nxt[maxm],lnk[maxn],tot;
inline int read() {
    int ret=0,f=1;char ch=getchar();
    for (; !isdigit(ch); ch=getchar()) if (ch=='-') f=-f;
    for (; isdigit(ch); ch=getchar()) ret=ret*10+ch-48;
    return ret*f;
}
inline void add_edge(int c,int f,int y,int x) {
    son[tot]=y,flw[tot]=f,cst[tot]=+c,nxt[tot]=lnk[x],lnk[x]=tot++;
    son[tot]=x,flw[tot]=0,cst[tot]=-c,nxt[tot]=lnk[y],lnk[y]=tot++;
}
inline bool spfa() {
    memset(vis,0,sizeof vis);
    memset(dis,0x3f,sizeof dis);
    dis[T]=0,Q.push_back(T);
    while (!Q.empty()) {
        int u=Q.front();
        vis[u]=0,Q.pop_front();
        for (register int k=lnk[u]; ~k; k=nxt[k])
            if (flw[k^1]>0&&dis[son[k]]>dis[u]-cst[k]) {
                dis[son[k]]=dis[u]-cst[k];
                if (!vis[son[k]]) {
                    vis[son[k]]=1;
                    if (!Q.empty()&&dis[u]<dis[Q.front()]) Q.push_front(son[k]);
                    else Q.push_back(son[k]);
                }
            }
    }
    vis[T]=1;
    return dis[S]<INF;
}
int dfs(int x,int flow) {
    vis[x]=1;
    if (x==T) return flow;
    int diss=0;
    for (register int k=lnk[x]; ~k; k=nxt[k])
        if (!vis[son[k]]&&flw[k]&&dis[son[k]]==dis[x]-cst[k]) {
            int d=dfs(son[k],min(flow,flw[k]));
            if (d<=0) continue;
            MC+=d*cst[k],flw[k]-=d,flw[k^1]+=d;
            diss+=d,flow-=d;
            if (flow==0) break;
        }
    return diss;
}
int main() {
    memset(lnk,-1,sizeof lnk);
    N=read(),M=read(),S=1,T=N;
    for (register int i=1; i<=M; i++) add_edge(read(),read(),read(),read());
    while (spfa()) while (vis[T]) memset(vis,0,sizeof vis),MF+=dfs(S,INF);
    printf("%d %d\n",MF,MC);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ZJ_JS_ZXB/article/details/80747747