网络流模板——矩阵实现


没有I/O操作,

flow[][], cap[][]记录了网络矩阵

node[]记录了  相连的点

path[]记录了  增广路径上进入的点

通过BFS搜索增广路径,然后通过path[]倒着更新。

#include <stdio.h>  
#include <vector>  
#include <queue>  
using namespace std;

//POJ 1459 Power Network  

const int MAXN = 100 + 2;
const int inf = 0x7fffffff;
char temp[20];      //buffer  
int main() {
	int n, l;			//点数,边数
	int S, T;			//Source, Terminal
	//矩阵初始化
	int flow[MAXN][MAXN], cap[MAXN][MAXN];
	for (int i = 0; i < MAXN; ++i)
		for (int j = 0; j < MAXN; ++j)
		{
			flow[i][j] = 0;
			cap[i][j] = 0;
		}
	vector<vector<int> > node(n);					//node[i]数组 表示和i相连的点

	//读边
	for (int i = 0; i < l; ++i)
	{
		int from, to, c;
		//read
		//.......do read
		//scanf("%s", temp); sscanf(temp, "(%d,%d)%d", &from, &to, &cc);
		cap[from][to] = c;
		if (cap[to][from])continue;			//平行边重复记录
		node[from].push_back(to);
		node[to].push_back(from);
	}


	int maxFlow = 0;
	vector<int> aug(n);					//aug[i] 表示S到i的可改进量  
	vector<int> path(n);				//p[i] 表示增广路径上的 i的进入点  

	//BFS查找增广路径  
	while (true)
	{
		for (int i = 0; i < n + 2; ++i)aug[i] = 0;
		queue<int>q;
		q.push(S);
		aug[S] = inf;
		while (!q.empty())
		{
			int x = q.front();
			q.pop();
			int size = node[x].size();
			for (int i = 0; i < size; ++i)
			{
				int t = node[x][i];
				if (aug[t])continue;				//访问过的就跳过,当然也可以不跳。。。

				//x->t
				if (cap[x][t] > flow[x][t])
				{
					path[t] = x;				//记录进入点
					aug[t] = min(aug[x], cap[x][t] - flow[x][t]);	//更新残存容量
					q.push(t);
				}

				//t->x
				else if (flow[t][x] > 0)
				{
					path[t] = x;				//记录进入点
					aug[t] = min(aug[x], flow[t][x]);				//更新残存容量
					q.push(t);
				}

			}
			if (aug[T])break;           //已经找到一条增广路径  

		}
		if (!aug[T])break;              //没有增广路径,结束,返回结果  

		//有增广路径,从path[]倒着更新  
		//这条路径上最小值就是aug[T]  
		int min_aug = aug[T];
		for (int u = T; u != S; u = path[u])
		{
			if (flow[path[u]][u] < cap[path[u]][u])
				flow[path[u]][u] += min_aug;
			else
				flow[u][path[u]] -= min_aug;
		}
		//流加上这个值  
		maxFlow += min_aug;
	}
	//没有增广路径,结束,返回结果  
	printf("%d\n", maxFlow);


	system("pause");
	return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值