最小费用最大流模板(POJ 2135-Farm Tour)

最近正好需要用到最小费用最大流,所以网上就找了这方面的代码,动手写了写,先在博客里存一下~

代码的题目是POJ2135-Farm Tour

需要了解算法思想的,可以参考下面一篇文章,个人觉得有最大流基础的童鞋,看了基本就能看懂了,通俗易懂。

https://www.cnblogs.com/gtarcoder/p/4890739.html

 

#include <iostream>
#include <string>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>

#define E 50000
#define maxn 1005
#define INF 0x3f3f3f3f
using namespace std;
struct Edge
{
    int u,v,flow,cost,next;
}edge[E];

int tot,head[maxn],pre[maxn],dist[maxn],vis[maxn];
int n,m;
void add(int u,int v,int flow,int cost)//flow为流量  cost为费用
{
    edge[tot].u=u;
    edge[tot].v=v;
    edge[tot].flow=flow;
    edge[tot].cost=cost;
    edge[tot].next=head[u];
    head[u]=tot++;
}

void addEdge(int u,int v,int flow,int cost){
    add(u,v,flow,cost);
    add(v,u,0,-cost);
}

bool SPFA(int s,int t,int n)
{
    int v,tmp;
    queue<int> q;
    for(int i=0;i<=n;i++)
       {
        pre[i]=-1;
        vis[i]=0;
        dist[i]=INF;
    }
    vis[s]=1;
    dist[s]=0;
    q.push(s);
    while(!q.empty())
       {
        tmp=q.front();
        q.pop();
        vis[tmp]=0;
        for(int k=head[tmp];k!=-1;k=edge[k].next)
            if(edge[k].flow){
                v=edge[k].v;
                if(dist[v]>dist[tmp]+edge[k].cost){
                    dist[v]=dist[tmp]+edge[k].cost;
                    pre[v]=k; //存储对应的边
                    if(!vis[v]){
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
    }
    return dist[t]!=INF;
}

int mcmf(int s,int t,int n)
{
    int flow=INF,ans=0;
    while(SPFA(s,t,n))
       {
        ans+=dist[t];
        for(int k=pre[t];k!=-1;k=pre[edge[k].u])
            flow=min(flow,edge[k].flow);
        for(int k=pre[t];k!=-1;k=pre[edge[k].u])
               {
            edge[k].flow-=flow;
            edge[k^1].flow+=flow;
        }
    }
    return ans;
}

void init(){
    for(int i=0;i<maxn;i++)
        head[i]=-1;
    tot=0;
}
int main()
{
    int n,m;
    scanf("%d %d",&n,&m);
    int s=0,t=n+1;
    init();
    for(int i=0;i<m;i++){
        int u,v,c;
        scanf("%d %d %d",&u,&v,&c);
        addEdge(u,v,1,c);
        addEdge(v,u,1,c);
    }
    addEdge(s,1,2,0);
    addEdge(n,t,2,0);
    int ans=mcmf(s,t,n+1);
    printf("%d\n",ans);
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/chenxiwenruo/p/6624255.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值