网络流模板


最大流


#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
#define CLR( a , x ) memset ( a , x , sizeof (a) );

const int maxm=1005;
const int maxn=20;
const int inf = 0x3f3f3f3f;
struct Dinic
{
    struct Edge
    {
        int v,w,next;
    }edge[maxm*2];
    int tol,head[maxn],dis[maxn];
    void addEdge(int u,int v,int w)
    {
        edge[tol].v=v,edge[tol].w=w,edge[tol].next=head[u];head[u]=tol++;
        edge[tol].v=u,edge[tol].w=0,edge[tol].next=head[v];head[v]=tol++;
    }
    void init()
    {
        tol=0;
        CLR(head,-1);
    }
    bool bfs(int s,int t)
    {
        queue<int>q;
        q.push(s);
        CLR(dis,-1);
        dis[s]=0;
        while(!q.empty())
        {
            int u=q.front();q.pop();
            for(int i=head[u];i!=-1;i=edge[i].next)
            {
                int v=edge[i].v;
                if( dis[v]<0 && edge[i].w)
                {
                    dis[v]=dis[u]+1;
                    q.push(v);
                }
            }
        }
        return dis[t]!=-1;
    }
    int dfs(int s,int t,int low)
    {
        int flow;
        if(t==s)   return low;
        for(int i=head[s];i!=-1;i=edge[i].next)
        {
            int v=edge[i].v;
            if(edge[i].w && (dis[v]==dis[s]+1) &&
                (flow = dfs(v,t,min(low,edge[i].w))))
            {
                edge[i].w -= flow;
                edge[i^1].w += flow;
                return flow;
            }
        }
        return 0;
    }
    int maxFlow(int s,int t)
    {
        int ans=0,tmp;
        while(bfs(s,t))
            while(tmp=dfs(s,t,inf))
                ans+=tmp;
        return ans;
    }
}DC;


使用例子:

int main()
{
    int t,m,n,a,b,c;
//    RE
    scanf("%d",&t);

    for(int te=1;te<=t;te++)
    {
        DC.init();
        scanf("%d%d",&n,&m);
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c);
            DC.addEdge(a,b,c);
        }
        printf("Case %d: %d\n",te,DC.maxFlow(1,n));
    }
    return 0;
}


费用流模板用结构体包装后内存占用稍大,如果有严格内存限制的话就拆开来,基本是kuangbin的


最小费用流

求最大费用只需要取相反数,结果取相反数即可

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
#define CLR( a , x ) memset ( a , x , sizeof (a) );

const int maxn = 200006;
const int maxm = 100006;
const int inf = 0x3f3f3f3f;
struct minCostDinic {
    struct Edge {
        int to, next, cap, flow, cost;
    } edge[maxm * 2];
    int head[maxn], tol;
    int pre[maxn], dis[maxn];
    bool vis[maxn];
    void init() {
        tol = 0;
        memset(head, -1, sizeof(head));
    }
    void addEdge(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);
                    }
                }
            }
        }
        return pre[t] != -1;
    }
    //返回最大流,cost存最小费用
    int minCostMaxflow(int s, int t, int &cost) {
        int flow = 0;
        cost = 0;
        while (spfa(s, t)) {
            int Min = inf;
            for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to]) {
                if (Min > edge[i].cap - edge[i].flow) {
                    Min = edge[i].cap - edge[i].flow;
                }
            }
            for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to]) {
                edge[i].flow += Min;
                edge[i ^ 1].flow -= Min;
                cost += edge[i].cost * Min;
            }
            flow += Min;
        }
        return flow;
    }
} costDC;



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值