网络流学习笔记

网络流学习笔记

第一天: 实现最基础网络流算法

基本思路

代码实现

#include <iostream>
#include <algorithm>
#include <queue>
#include <memory.h> 
using namespace std;
const int MAXN = 100;
const int MAXM = MAXN*MAXN;
const int INF = 0x3f3f3f3f;
int head[MAXN], Next[MAXM], ver[MAXM], edge[MAXM], flow[MAXM];
int tot;

void init(){
	tot = 0;
	memset(head, 0, sizeof(head));
}
void add(int x, int y, int z, int f){
	Next[++tot] = head[x];
	head[x] = tot;
	ver[tot] = y;
	edge[tot] = z;
	flow[tot] = f;
}

void add2(int x, int y, int z){
	add(x, y, z, 0);
	add(y, x, z, z);
}
int ss, tt, res[MAXN], pre[MAXN], v[MAXN], pre_index;
int bfs(){
	int x = ss;
	queue <int> q;
	while(!q.empty()) q.pop();
	memset(pre, 0, sizeof(pre));
	memset(res, 0, sizeof(res));
	memset(v, 0, sizeof(v));
	pre_index = 0;
	res[x] = INF;

	q.push(x);
	v[x] = 1;
	int c = 0;
	while(!q.empty()){
		x = q.front(); q.pop();
		for(int i = head[x]; i; i = Next[i]){
			int y = ver[i], z = edge[i], f = flow[i];
			
			//cout << y <<"flow"<<f<<endl;
			int fr = z-f;
			//可流判断
			if(fr > 0){
				if(v[y]) continue;
				c++;
				cout << c << x << "->" << y << ":" << fr << endl; 
				int t = min(res[x], fr);
				res[x]-=t;
				res[y]+=t;
				q.push(y);
				v[y] = 1;
				pre[pre_index++] = i;
				if(y == tt){
					return t;
				}
			}
		}
	}
	return 0;
}


int EK(){
	int f = 0, ans = 0;
	while(1){
		cout << f << endl;
		for(int i = 0; i < pre_index; i++){
			//cout << "iii" << pre[i] << endl;
			flow[pre[i]] += f;
			flow[pre[i]%2?pre[i]-1:pre[i]+1] -= f;
		}
		ans+=f;
		f = bfs();
		if(f == 0) break;
	}
	return ans;
}
int main(){
	//输入n点m边
	//节点编号从1开始
	int n, m;
	cin >> n >> m;
	cin >> ss >> tt;
	init();
	for(int i = 1; i <= m; i++){
		int a, b, z, f;
		cin >> a >> b >> z;
		add2(a, b, z);
	}
	cout << EK() << endl;
}
/*
6 8
1 4
1 6 2
6 5 1
5 4 3
3 4 2
1 4 3
2 3 1
1 2 2
1 3 2
*/ 

遇到问题

死循环
  1. 邻接表的终止值是0还是-1需要考虑清楚
bfs搜索错误
  1. 由于可能出现环,需要标记进入队列的点,借用spaf算法的标记方式,保证不因为环而死循环
posted @ 2019-03-30 16:07  Phoenix_Xie  阅读(149)  评论(0编辑  收藏  举报