最小费用流 Bellman-Ford与Dijkstra 模板

今天刚接触最小费用流 码下两个版本当作模板用吧 spfa的做法明天再整理

有负权边的情况只能用Bellman-Ford 没有的话就用Dijkstra 毕竟Dijkstra效率更高



首先贴下Bellman-Ford 实现最小费用流的算法 时间复杂度为 O(FEV)   F E V 分别代表需要传输的流量 边的条数 节点的个数


// Bellman_Ford
//Bellman—Ford算法

//Bellman算法求最短增广路&最小费用流 O(FEV)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef long long ll;
using namespace std;
#define MV 11000 //顶点的最大个数
#define INF 0x3f3f3f3f

struct edge
{
    int t, cap, cost, rev;
    edge(int to = 0, int c = 0, int ct = 0, int r = 0): t(to), cap(c), cost(ct), rev(r) {};
};
vector  G[MV];
int dis[MV];//the distance from source
int prevv[MV], preve[MV];//the previous node and the previous edge

int min_cost_flow(int n,int v,int s, int t, int f)//与main函数中的变量意义相同
{
    
    int ans = 0, i, j;
    while(f > 0)
    {
        fill(dis, dis + v, INF);
        dis[s] = 0;
        bool update = true;
        while(update)
        {//bellman
            update = false;
            for(i = 0; i < v; ++i)
            {
                int size1 = G[i].size();
                if(dis[i] == INF)
                    continue;
                for(j = 0; j < size1; ++j)
                {
                    edge &es = G[i][j];
                    if(es.cap > 0 && dis[es.t] > dis[i] + es.cost)
                    {
                        dis[es.t] = dis[i] + es.cost;
                        prevv[es.t] = i;
                        preve[es.t] = j;
                        update = true;
                    }
                }
            }
        }
        
        if(dis[t] == INF)
            return -1;
        int d = f;
        for(i = t; i != s; i = prevv[i])
            d = min(d, G[prevv[i]][preve[i]].cap);
        
        ans += d * dis[t];
        f -= d;
        for(i = t; i != s; i = prevv[i])
        {
            edge &es = G[prevv[i]][preve[i]];
            es.cap -= d;
            G[es.t][es.rev].cap += d;
        }
    }
    return ans;
}


void addedge(int s1,int t1,int cap,int cost)//依次为边的起点 终点 容量 花费
{
    G[s1].push_back(edge(t1, cap, cost, G[t1].size()));
    G[t1].push_back(edge(s1, 0, -cost, G[s1].size() - 1));
}
int main()
{
    int n, v, s, t, f;//n 是边的条数
                      // v 节点的个数(包括源点和汇点)
                      // s source   t sink
                     // f为需要传送的流量
    return 0;
}


---------------------------------------------------------------------------------


Dijkstra算法  复杂度为O(FElogV)     F E V 分别代表需要传输的流量 边的条数 节点的个数


#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef long long ll;
using namespace std;


#define MV 11000 //节点最大值
#define INF 0x3f3f3f3f


struct edge
{
    int t, cap, cost, rev;
    edge(int to = 0, int c = 0, int ct = 0, int r = 0): t(to), cap(c), cost(ct), rev(r) {};
};
vector  G[MV];//图的邻接表表示   注意!如果有多个样例输入 每个样例不要忘记G[i].clear();
int dis[MV];//单源点s到其它顶点的最短距离(本次搜索的最小费用)
int prevv[MV], preve[MV];//最短路中的前驱结点 对应边
int h[MV];

//最小费用流Dijkstra算法

//Dijkstra算法求最小费用流核心代码:

//h[MAX_V]:导入势保证所有边均为非负边 O(FElogV)
typedef pairP;
int min_cost_flow(int n, int v, int s, int t, int f) //与main函数中的变量对应一致
{
    
    int i, ans = 0;
    
    memset(h,0,sizeof h);
    
    while(f > 0)
    {
        //Dijkstra算法:寻找最短路 O(ElogV)
        priority_queue, greater

> que; fill(dis, dis + v, INF); dis[s] = 0; que.push(P(0, s)); while(!que.empty()) { P p = que.top(); que.pop(); int v = p.second; if(dis[v] < p.first) continue; int size = G[v].size(); for(i = 0; i < size; ++i) { edge es = G[v][i];//**** if(es.cap > 0 && dis[es.t] > dis[v] + es.cost + h[v] - h[es.t]) { dis[es.t] = dis[v] + es.cost + h[v] - h[es.t]; prevv[es.t] = v; preve[es.t] = i; que.push(P(dis[es.t], es.t)); } } } if(dis[t] == INF) return -1; //更新势 for(i = 0; i < v; ++i) h[i] += dis[i]; int d = f; for(i = t; i != s; i = prevv[i]) d = min(d, G[prevv[i]][preve[i]].cap); ans += d * h[t]; f -= d; for(i = t; i != s; i = prevv[i]) { edge &es = G[prevv[i]][preve[i]]; es.cap -= d; G[i][es.rev].cap += d; } } return ans; } void addedge(int s1,int t1,int cap,int cost) { G[s1].push_back(edge(t1, cap, cost, G[t1].size())); G[t1].push_back(edge(s1, 0, -cost, G[s1].size() - 1)); } int main() { int n, v, s, t, f;//n 边的条数 // v 节点的数量(包括源点和汇点) // s source t sink // f 需要传送的流量 return 0; }



这两个模板与白书上的类似 可以直接拿去用 明天更新spfa();

(只能说明我现在还没有很好的理解掌握spfa算法)


你可能感兴趣的:(ACM,最大流,最小费用流)