最大流模板

Edmods_Karp 算法

时间复杂度: O(n * m * m)

//EK
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#define CLR(arr, v) memset(arr, v, sizeof(arr))
#pragma warning (disable:4996)
using namespace std;

const int MaxE = 100 * 2;    //注意乘以2
const int MaxV = 100;
const int INF = 1e9;

struct Graph
{
	struct Vertex
	{
		int head;
	}V[MaxV];
	struct Edge
	{
		int v, c, f, next;
		Edge(){};
		Edge(int v, int c,int f, int next):v(v), c(c), f(f), next(next){}
	}E[MaxE];
	int top;
	void init()
	{
		top = 0;
		CLR(V, -1);
	}
	void addEdge(int u, int v, int c)
	{
		E[top] = Edge(v, c, 0, V[u].head);
		V[u].head = top++;
		E[top] = Edge(u, 0, 0, V[v].head);
		V[v].head = top++;
	}
};

Graph g;
int vexNum, edgeNum;  //点数, 边数
int s, t;             //源点, 汇点
int path[MaxV];       //记录路径
int flow[MaxV];       //记录增光路上面的流

bool bfs()
{
	CLR(flow, 0);      //注意每次初始化
	queue<int> Q;
	Q.push(s);     
	flow[s] = INF;

	while(!Q.empty())
	{
		int top = Q.front();

		for(int i = g.V[top].head; i != -1; i = g.E[i].next)
		{
			int v = g.E[i].v;
			if(g.E[i].f < g.E[i].c && !flow[v])     //千万别忘了!flow[v]
			{
				path[v] = i;
				flow[v] = min(flow[top], g.E[i].c - g.E[i].f);   //is flow[top]
				if(v == t)
					return true;
				Q.push(v);
			}
		}
		Q.pop();
	}
	return false;
}


int EK()
{
	int i, maxFlow = 0;
	while(bfs())
	{
		for(int v = t; v != s; v = g.E[i ^ 1].v)   //这一这个地方的i
		{
			i = path[v];
			g.E[i].f      += flow[t];
			g.E[i ^ 1].f  -= flow[t];
		}
		maxFlow += flow[t];
	}
	return maxFlow;
}
int main()
{
	g.init();       //每次初始化

	scanf("%d %d", &vexNum, &edgeNum);
	for(int i = 0; i < edgeNum; i++)
	{
		int u, v, w;
		scanf("%d %d %d", &u, &v, &w);
		g.addEdge(u, v, w);
	}
	s = 1, t = vexNum;
	printf("%d\n", EK());

}

Dinic 算法:

复杂度:O(n * n * m)

//Dinic
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>

#define CLR(arr, val) memset(arr, val, sizeof(arr))
#pragma warning(disable:4996)

using namespace std;

const int INF = 1e9;
const int MaxE = 100 * 2;
const int MaxV = 100;


struct Graph
{
	struct Vertex
	{
		int head;
	}V[MaxV];

	struct Edge
	{
		int v, c, next;
		Edge(int v,int c, int next):v(v), c(c), next(next){}
		Edge(){}
	}E[MaxE];
	void init()
	{
		top = 0;
		CLR(V, -1);
	}
	void addEdge(int u, int v, int c)
	{
		E[top] = Edge(v, c, V[u].head);
		V[u].head = top++;
		E[top] = Edge(u, 0, V[v].head);
		V[v].head = top++;
	}
	int top;
};

int level[MaxV];
int path[MaxV];
int s, t;
Graph g;

bool bfs()
{
	CLR(level, -1);
	level[s] = 0;
	queue<int>Q;
	Q.push(s);

	while(!Q.empty())
	{
		int top = Q.front();

		for(int i = g.V[top].head; i != -1; i = g.E[i].next)
		{
			int v = g.E[i].v;
			if(level[v] == -1 && g.E[i].c)
			{
				level[v] = level[top] + 1;
				Q.push(v);
			}
		}
		Q.pop();
	}
	return level[t] != -1;
}

int dfs(int cur, int c)
{
	if(cur == t)
	{
		return c;
	}
	int sum = c;

	for(int i = g.V[cur].head; i != -1; i = g.E[i].next)
	{
		int v = g.E[i].v;
		if(g.E[i].c > 0 && level[v] == level[cur] + 1)
		{
			int a = dfs(v, min(c, g.E[i].c));
			g.E[i].c      -= a;       //注意Dinic算法不是专门用一个变量记录逆流, 所以这里与spa不同
			g.E[i ^ 1].c  += a;
			c -= a;
		}
	}
	return sum - c;
}

int dinic()
{
	int maxFlow = 0;
	while(bfs())
	{
		maxFlow += dfs(1, INF);
	}
	return maxFlow;
}

int vexNum, edgeNum;

int main(){

	g.init();
	scanf("%d %d", &vexNum, &edgeNum);
	for(int i = 0; i < edgeNum; i++)
	{
		int u, v, w;
		scanf("%d %d %d", &u, &v, &w);
		g.addEdge(u, v, w);
	}
	s = 1, t = vexNum;
	printf("%d\n", dinic());
	return 0;
}


SPA算法:

复杂度O(n * n *m)

复杂度和Dinic一样, 但是经过各种优化后比Dinic稍好一些

//SPA
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <vector>
#include <iostream>

#define CLR(arr, val) memset(arr, val, sizeof(arr))
#pragma warning(disable:4996)

using namespace std; 

const int MaxV = 1003;
const int MaxE = 10000 << 1;
const int INF = 1e9;

struct Graph
{
	struct Vertex
	{
		int head;
	}V[MaxV];

	struct Edge 
	{
		int v, c, f, next;
		Edge(){}
		Edge(int v,int c, int f, int next):v(v), c(c), f(f), next(next){}
	}E[MaxE];

	void init()
	{
		top = 0;
		CLR(V, -1);
	}
	void addEdge(int u, int v,int w)
	{
		E[top] = Edge(v, w, 0, V[u].head);
		V[u].head = top++;
		E[top] = Edge(u, 0, 0, V[v].head);
		V[v].head = top++;
	}
	int top;
};



int s, t, vexNum;
int h[MaxV],pre[MaxV],cur[MaxV],gap[MaxV];
Graph g;

void setHeight()  
{  
	queue<int> Q;  
	CLR(h,-1);  
	CLR(gap,0);  
	h[t] = 0;  
	Q.push(t);  
	while(!Q.empty())  
	{  
		int v = Q.front();  
		Q.pop();  
		++gap[ h[v] ];  
		for(int i=g.V[v].head;i!=-1;i=g.E[i].next)  
		{  
			int u = g.E[i].v;  
			if(h[u] == -1)  
			{  
				h[u] = h[v]+1;  
				Q.push(u);  
			}  
		}  
	}  
}  

int sap()  
{  
	setHeight();                                        //You can replace it with "CLR(d,0)" if you feel it trouble  
	int MaxFlow = 0, u = s;  
	int flow = INF;  
	memcpy(cur,g.V,sizeof(g.V));                        //current arc  
	while(h[s] < vexNum)  
	{  
		int &i = cur[u];                            //reference  
		for(;i!=-1;i=g.E[i].next)  
		{  
			int v = g.E[i].v;  
			if(g.E[i].c > g.E[i].f && h[u] == h[v]+1)  //admissible arc  
			{  
				u = v;  
				pre[v] = i;  
				flow = min(flow,g.E[i].c-g.E[i].f);  
				if(u == t)  
				{  
					while(u != s)  
					{  
						int j = pre[u];  
						g.E[j].f   += flow;  
						g.E[j^1].f -= flow;  
						u = g.E[j^1].v;  
					}  
					MaxFlow += flow;  
					flow = INF;  
				}  
				break;  
			}  
		}  
		if(i == -1)                                //there's no admissible arc.  
		{  
			if(--gap[ h[u] ] == 0)  
				break;  
			int dmin = vexNum-1;  
			cur[u] = g.V[u].head;  
			for(int j=g.V[u].head;j!=-1;j=g.E[j].next)  
				if(g.E[j].c > g.E[j].f)                //not full arc  
					dmin = min(dmin,h[ g.E[j].v ]);  
			h[u] = dmin+1;  
			++gap[ h[u] ];  
			if(u != s)  
				u = g.E[ pre[u]^1 ].v;  
		}  
	}  
	return MaxFlow;  
}

int main(){int ncase, tmp = 1;scanf("%d", &ncase);while(ncase--){g.init();scanf("%d %d", &vexNum, &edgeNum);while(edgeNum--){int u, v, w;scanf("%d %d %d", &u, &v, &w);g.addEdge(u, v, w);}s = 1, t = vexNum;printf("Case %d: %d\n", tmp++, sap());}return 0;}

所有的主函数都是针对HDU3549所写的



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值