模板 - 最小费用最大流

SPFA版本:

#include<bits/stdc++.h>
using namespace std;


namespace SPFA_Mincost_Maxflow {
    const int MAXN=10000;
    const int MAXM=100000;
    const int INF=0x3f3f3f3f;

    struct Edge {
        int to,next,cap,flow,cost;
    } edge[MAXM];

    int head[MAXN],tol;

    int pre[MAXN],dis[MAXN];
    bool vis[MAXN];

    void init() {
        tol=0;
        memset(head,-1,sizeof(head));
    }

    void add_edge(int u,int v,int cap,int cost) {
        edge[tol].to=v;
        edge[tol].cap=cap;
        edge[tol].cost=cost;
        edge[tol].flow=0;
        edge[tol].next=head[u];
        head[u]=tol++;

        edge[tol].to=u;
        edge[tol].cap=0;
        edge[tol].cost=-cost;
        edge[tol].flow=0;
        edge[tol].next=head[v];
        head[v]=tol++;
    }

    bool spfa(int s,int t) {
        queue<int> q;
        memset(dis,INF,sizeof(dis));
        memset(vis,false,sizeof(vis));
        memset(pre,-1,sizeof(pre));

        dis[s]=0;
        vis[s]=true;
        q.push(s);
        while(!q.empty()) {
            int u=q.front();
            q.pop();
            vis[u]=false;
            for(int i=head[u]; i!=-1; i=edge[i].next) {
                int v=edge[i].to;
                if(edge[i].cap>edge[i].flow&&dis[v]>dis[u]+edge[i].cost) {
                    dis[v]=dis[u]+edge[i].cost;
                    pre[v]=i;
                    if(!vis[v]) {
                        vis[v]=true;
                        q.push(v);
                    }
                }
            }
        }
        if(pre[t]==-1)
            return false;
        else
            return true;
    }

    int mincost,maxflow;

    void mincost_maxflow(int s,int t) {
        int cost=0,flow=0;
        while(spfa(s,t)) {
            int tp=INF;
            for(int i=pre[t]; i!=-1; i=pre[edge[i^1].to]) {
                if(tp>edge[i].cap-edge[i].flow)
                    tp=edge[i].cap-edge[i].flow;
            }
            for(int i=pre[t]; i!=-1; i=pre[edge[i^1].to]) {
                edge[i].flow+=tp;
                edge[i^1].flow-=tp;
                cost+=edge[i].cost*tp;
            }
            flow+=tp;
        }
        mincost=cost;
        maxflow=flow;
        return;
    }

}


using namespace SPFA_Mincost_Maxflow;


int main() {
    int N,M,S,T;
    scanf("%d%d%d%d",&N,&M,&S,&T);
    init();

    while(M--) {
        int u,v,cap,cost;
        scanf("%d%d%d%d",&u,&v,&cap,&cost);
        add_edge(u,v,cap,cost);
    }

    mincost_maxflow(S,T);

    printf("%d %d\n",maxflow,mincost);
}


Dijkstra版本:

这个版本不容易被卡,据说会快70%。缺点是要控制负数费用不能负得太离谱,不然换 long long 试试吧。 ```cpp #include using namespace std; typedef long long ll; typedef pair pii;

const int maxn = 5000;
const int INF = 0x3f3f3f3f;

struct Edge {
int to, cap, cost, flow;
Edge() {}
Edge(int to, int _cap, int _cost, int _flow) : to(to), cap(_cap), cost(_cost), flow(_flow) {}
};

struct MinCostMaxFlow {
int V, H[maxn + 5], dis[maxn + 5], prev[maxn + 5], pree[maxn + 5];
vector G[maxn + 5];
//调用前初始化
void init(int n) {
V = n;
for(int i = 0; i <= V; ++i)
G[i].clear();
}
//加边
void addEdge(int from, int to, int cap, int cost) {
G[from].push_back(Edge(to, cap, cost, G[to].size()));
G[to].push_back(Edge(from, 0, -cost, G[from].size() - 1));
}
//flow是自己传进去的变量,就是最后的最大流,返回的是最小费用
int minCostMaxFlow(int s, int t, int f, int& flow) {
int cost = 0;
fill(H, H + 1 + V, 0);
while(f) {
priority_queue <pii, vector, greater > q;
fill(dis, dis + 1 + V, INF);
dis[s] = 0;
q.push(pii(0, s));
while(!q.empty()) {
pii now = q.top();
q.pop();
int v = now.second;
if(dis[v] < now.first)
continue;
for(int i = 0; i < G[v].size(); ++i) {
Edge& e = G[v][i];
if(e.cap > 0 && dis[e.to] > dis[v] + e.cost + H[v] - H[e.to]) {
dis[e.to] = dis[v] + e.cost + H[v] - H[e.to];
prev[e.to] = v;
pree[e.to] = i;
q.push(pii(dis[e.to], e.to));
}
}
}
if(dis[t] == INF)
break;
for(int i = 0; i <= V; ++i)
H[i] += dis[i];
int d = f;
for(int v = t; v != s; v = prev[v])
d = min(d, G[prev[v]][pree[v]].cap);
f -= d, flow += d, cost += d * H[t];
for(int v = t; v != s; v = prev[v]) {
Edge& e = G[prev[v]][pree[v]];
e.cap -= d;
G[v][e.flow].cap += d;
}
}
return cost;
}
} mcmf;

inline int read() {
char ch = getchar();
int x = 0;
while(ch < '0' || ch > '9')
ch = getchar();
while(ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + ch - '0';
ch = getchar();
}
return x;
}

int a[2005];
int main() {

ifdef Yinku

freopen("Yinku.in", "r", stdin);

endif // Yinku

for(int T = read(); T; --T) {
    int n = read(), k = read();
    int s1 = 0, s2 = 2 * n + 1, t = 2 * n + 2;
    mcmf.init(2 * n + 2);
    mcmf.addEdge(s1, s2, k, 0);
    for(int i = 1; i <= n; ++i) {
        a[i] = read();
        mcmf.addEdge(i, i + n, 1, -a[i]);
        mcmf.addEdge(s2, i, 1, 0);
        mcmf.addEdge(i + n, t, 1, 0);
    }
    for(int i = 1; i <= n; ++i)
        for(int j = i + 1; j <= n; ++j)
            if(a[j] >= a[i])
                mcmf.addEdge(i + n, j, 1, 0);
    int flow = 0;
    printf("%d\n", -mcmf.minCostMaxFlow(s1, t, INF, flow));
}

}


</details>
posted @ 2019-04-15 17:31  韵意  阅读(121)  评论(0编辑  收藏  举报