码迷,mamicode.com
首页 > 其他好文 > 详细

最小费用流

时间:2019-09-13 01:07:03      阅读:90      评论:0      收藏:0      [点我收藏+]

标签:开始   相同   cap   入门   index   起点   窗口   cout   pop   

// algorithm_minimum_cost_stream.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
//https://blog.csdn.net/qq_43824791/article/details/93238445

#include "pch.h"
#include <iostream>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;
#define inf 0x3f3f3f3f
#define maxN 400
#define maxM 15000

struct Edge {
    int head, tail;
    int next;
    int cap, flow;
    int weight;
}edge[maxM*2];

int headArray[maxN];//各起点分别拥有的最新的边的号
int preArray[maxN];
int dist[maxN];
bool vst[maxN];
int index_edge;
int n, m, s, t;


void addedge(int head, int tail, int c, int w)
{
    edge[index_edge].head = head;
    edge[index_edge].tail = tail;
    edge[index_edge].cap = c;
    edge[index_edge].flow = 0;
    edge[index_edge].weight = w;

    edge[index_edge].next = headArray[head];
    headArray[head] = index_edge++;


    edge[index_edge].head = tail;
    edge[index_edge].tail = head;
    edge[index_edge].cap = 0;
    edge[index_edge].flow = 0;
    edge[index_edge].weight = -w;
    edge[index_edge].next = headArray[tail];
    headArray[tail] = index_edge++;
}

bool SPFA()
{
    memset(dist, 0x3f, sizeof(dist));
    memset(vst, 0, sizeof(vst));
    queue<int >que;

    dist[s] = 0;//这里就没设为1,s一般题目中都为1
    vst[s] = 1;
    que.push(s);
    while (!que.empty())
    {
        int i = que.front();
        que.pop();
        vst[i] = 0;
        for (int edg_index = headArray[i]; edg_index != -1; edg_index = edge[edg_index].next)
        {
            int j = edge[edg_index].tail;
            if (edge[edg_index].cap > edge[edg_index].flow && dist[j] > dist[i] + edge[edg_index].weight)
            {
                dist[j] = dist[i] + edge[edg_index].weight;
                preArray[j] = edg_index;//记住边的号
                if (!vst[j])
                {
                    vst[j] = 1;
                    que.push(j);
                }
            }
        }
    }
    if (dist[t] != inf)
        return true;
    return false;
}



int costflow(int &flow)
{
    int mincost = 0;
    while (SPFA())
    {
        int delta = inf;
        for (int j = t; j != s; j = edge[preArray[j]].head)
        {
            delta = min(delta, edge[preArray[j]].cap - edge[preArray[j]].flow);

        }

        for (int j = t; j != s; j = edge[preArray[j]].head)
        {
            edge[preArray[j]].flow += delta;
            edge[preArray[j]+1].flow -= delta;
        }
        flow += delta;
        mincost += (dist[t] * delta);//每一次迭代,所用的delta是相同的都是一部分增量
    }
    return mincost;
}
int main()
{
    index_edge = 0;

    memset(headArray, -1, sizeof(headArray));
    
    cin >> n >> m;
    s=1 ,t=n;
    for (int i = 0; i < m; i++)
    {
        int  a, b, c, w;
        cin >> a >> b >> c >> w;
        addedge(a, b, c, w);
    }
    int maxflow = 0;
    int mincost = costflow(maxflow);
    cout << maxflow<<" " << mincost;
   // std::cout << "Hello World!\n";
    return 0;
}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门提示:
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件

最小费用流

标签:开始   相同   cap   入门   index   起点   窗口   cout   pop   

原文地址:https://www.cnblogs.com/Jonn-Liu/p/11515593.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!