Kdmonds-Karp(增广路算法)和BellmanFord算法

最大流(Kdmonds-Karp)算法 

#include <iostream>
#include <queue>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 1000 + 10;
const int inf = 0x3f3f3f3f;
struct Edge {
	int from, to, cap, flow;
	Edge(int from = 0, int t = 0, int c = 0, int flow = 0) :from(from), to(t), cap(c), flow(flow) {}
};

struct Edmond_Karp {
	int n, m;
	vector<Edge> edges;
	vector<int> G[maxn];
	int a[maxn];
	int p[maxn];

	void init() {
		for (int i = 0; i < n; i++)G[i].clear();
		edges.clear();
	}
	void Add_Edge(int f, int t, int c) {
		edges.push_back(Edge(f, t, c, 0));
		edges.push_back(Edge(t, f, 0, 0));
		m = edges.size();
		G[f].push_back(m - 2);
		G[t].push_back(m - 1);
	}
	int Maxflow(int s, int t)
	{
		int flow = 0;
		for (;;)
		{
			memset(a, 0, sizeof(a));
			queue<int> q;
			q.push(s);
			a[s] = inf;
			while (!q.empty()) {
				int x = q.front(); q.pop();
				for (int i = 0; i < G[x].size(); i++)
				{
					Edge& e = edges[G[x][i]];
					if (!a[e.to] && e.cap > e.flow) {
						p[e.to] = G[x][i];
						a[e.to] = min(a[x], e.cap - e.flow);
						q.push(e.to);
					}
				}
				if (a[t])break;
			}
			if (!a[t])break;

			for (int u = t; u != s; u = edges[p[u]].from)
			{
				edges[p[u]].flow += a[t];
				edges[p[u] ^ 1].flow -= a[t];
			}
			flow += a[t];
		}
		return flow;
	}
};

 BellmanFord算法的最小费用最大流

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

const int maxn = 1000 + 10;
const int INF = 0x3f3f3f3f;

struct Edge {
	int from, to, cap, flow, cost;
	Edge(int f, int t, int c, int f1, int c1) :from(f), to(t), cap(c), flow(f1), cost(c1) {}
};

struct MCMF {
	int n, m;
	vector<int> G[maxn];
	vector<Edge> edges;
	int a[maxn];
	int p[maxn];
	int inq[maxn];//是否在队列
	int d[maxn];//Bellman-Ford

	void init(int n) {
		this->n = n;
		for (int i = 0; i < n; i++)G[i].clear();
		edges.clear();
	}

	void AddEdge(int from, int to, int cap, int cost) {
		edges.push_back(Edge(from, to, cap, 0, cost));
		edges.push_back(Edge(to, from, 0, 0, -cost));
		m = edges.size();
		G[from].push_back(m - 2);
		G[to].push_back(m - 1);
	}

	bool BellmanFord(int s, int t, int& flow, long long& cost) {
		for (int i = 0; i < n; i++)d[i] = INF;
		memset(inq, 0, sizeof(inq));
		d[s] = 0, p[s] = 0, inq[s] = 1, a[s] = INF;
		queue<int> q;
		q.push(s);
		while (!q.empty()) {
			int u = q.front(); q.pop();
			inq[u] = 0;
			for (int i = 0; i < G[u].size(); i++) {
				Edge& e = edges[G[u][i]];
				if (e.cap > e.flow && d[e.to] > d[u] + e.cost) {
					d[e.to] = d[u] + e.cost;
					p[e.to] = G[u][i];
					a[e.to] = min(a[u], 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 += (long long)d[t] * (long long)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 MincostMinflow(int s, int t, long long& cost) {
		int flow = 0, cost = 0;
		while (BellmanFord(s, t, flow, cost));
		return flow;
	}
};

两个模板题目碰到求最大流或者费用流或者是二分图的匹配可以直接用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值