網絡流學習筆記
第一天: 實現最基礎網絡流算法
基本思路
代碼實現
#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
*/
遇到問題
死循環
- 鄰接表的終止值是0仍是-1須要考慮清楚
bfs搜索錯誤
- 因爲可能出現環,須要標記進入隊列的點,借用spaf算法的標記方式,保證不由於環而死循環