Help Little Laura UVA - 1659(最大费用循环流--->转换为最小费用流)

该博客介绍了如何使用最小费用最大流(Mincost Maxflow)算法来解决包含负权边的网络问题。文章通过实例展示了如何构建网络图,并利用Bellman-Ford算法求解最小费用路径,从而实现最大流量与最小费用的平衡。最后,通过一个具体的实例解释了算法的实现过程和输出结果。
摘要由CSDN通过智能技术生成

Help Little Laura UVA - 1659

看这里即可

什么是最小费用循环流

为什么正确+题解&&模板

AC

#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#define mst(x, a) memset(x,a, sizeof(x))
#define sz(a) (int)a.size()
#define For(i,x,y) for(int i=(x); i<=(y); i++)
#define fori(i,x,y) for(int i=(x); i<(y); i++)
#define pb push_back
#define fzhead EDGE(int u, int v, int c, int f, double w)
#define fzbody from(u), to(v), cap(c), flow(f), cost(w)
using namespace std;
const double eps = 1e-8;
const double INF = 1e38;
const int inf = 0x3f3f3f3f;
const int maxn = 110;
struct EDGE{
    int from, to, cap, flow;
    double cost;
    EDGE(){}
    fzhead : fzbody {}
};
struct MCMF{
    int n, m, s, t;
    vector<EDGE>edges;
    vector<int>G[maxn];
    int inq[maxn];
    double d[maxn];
    int p[maxn];
    int a[maxn];
    void init(int n){
        this->n = n;
        fori(i,0,n)G[i].clear();
        edges.clear();
    }
    void AddEdge(int from, int to, int cap, double cost){
        edges.pb({from, to, cap, 0, cost});
        edges.pb({to, from, 0, 0, -cost});
        m = edges.size();
        G[from].pb(m-2);
        G[to].pb(m-1);
    }
    bool BellmanFord(int s,int t, int& flow, double& cost){
        fori(i,0,n) d[i] = INF;
        mst(inq,0);
        d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = inf;
        queue<int>q; q.push(s);
        while(!q.empty()){
            int x = q.front(); q.pop();
            inq[x] = 0;
            fori(i,0,sz(G[x])){
                EDGE& e = edges[G[x][i]];
                if(e.cap > e.flow && d[e.to] > d[x] + e.cost){
                    d[e.to] = d[x] + e.cost;
                    p[e.to] = G[x][i];
                    a[e.to] = min(a[x], e.cap - e.flow);
                    if(!inq[e.to]) {q.push(e.to); inq[e.to] = 1;}
                }
            }
        }
        if(d[t] == INF)return false;
        flow += a[t];
        cost += d[t] * a[t];
        for(int u= t; u != s; u = edges[p[u]].from){
            edges[p[u]].flow += a[t];
            edges[p[u]^1].flow -= a[t];
        }
        return true;
    }
    int MincostMaxflow(int s, int t, double& cost){
        int flow = 0;
        while(BellmanFord(s, t, flow, cost));
        return flow;
    }
}mcmf;
int n;
int earn, lost;
int st, ed;
int x[maxn], y[maxn], degree[maxn];
double ans;
vector<int> e[maxn];
double getdis(int i, int j){return sqrt((x[i]-x[j]) * (x[i]-x[j]) + (y[i]-y[j]) * (y[i]-y[j]));}
void init(){
    scanf("%d%d", &earn, &lost);
    int u, v;
    ans = 0;
    st = 0; ed = n+1;
    For(i,1,n) e[i].clear(), degree[i] = 0;
    For(u,1,n){
        scanf("%d%d", &x[u], &y[u]);
        while(scanf("%d", &v)&&v)e[u].pb(v);
    }
    mcmf.init(maxn);
    For(u,1,n){
        fori(i,0,sz(e[u])){
            v = e[u][i];
            double cost = lost-getdis(u,v)*earn;
            if(cost < 0){/// postive v -> u
                ans += cost;
                degree[v]--; degree[u]++;
                mcmf.AddEdge(v,u,1,-cost);
            }else mcmf.AddEdge(u,v,1,cost);
        }
    }
    For(u,1,n){
        if(degree[u] > 0) mcmf.AddEdge(u, ed, degree[u], 0);
        if(degree[u] < 0) mcmf.AddEdge(st, u, -degree[u], 0);
    }
}
int main()
{
    int kase = 0;
    //ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    while(scanf("%d", &n)&&n){
        init();
        mcmf.MincostMaxflow(st,ed,ans);
        printf("Case %d: %.2f\n",++kase,-ans+eps);
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值