来篇EK算法的题解。
这里用的是邻接表,跑的快一点,因为可以压缩一下重边。
EK算法的本质就是不断的寻找增广路,然后把找到的所有增广路的流量累加起来。详细的可以看一下洛咕日报的这篇博客。
一些细节会在代码里面指出。
代码:
#include <bits/stdc++.h>
using namespace std;
long long n , m , s , t , ans;
long long pre[200010] , dis[2010][2010] , vis[200010] , minn[200010];
vector<int> e[200010];
bool bfs(){
memset(vis , 0 , sizeof(vis));
queue<int> q;
vis[s] = 1;
q.push(s);
minn[s] = 0x3ffffff;
while(!q.empty()){
int x = q.front();
q.pop();
for(int i = 0; i < e[x].size(); i++){
int nx = e[x][i];
if(dis[x][nx] > 0){
if(vis[nx]) continue;
minn[nx] = min(minn[x] , dis[x][nx]); //找出最小容量
pre[nx] = x; //记录前驱
q.push(nx);
vis[nx] = 1;
if(nx == t) return 1;
}
}
}
return 0;
}
void update(){ //更新剩余容量
int x = t;
while(x != s){
int px = pre[x];
dis[x][px] += minn[t];
dis[px][x] -= minn[t];
x = px;
}
ans += minn[t];
}
int main(){
cin >> n >> m >> s >> t;
for(int i = 1; i <= m; i++){
int x , y , z;
cin >> x >> y >> z;
e[x].push_back(y);
dis[x][y] += z; //有可能会有重边,需要把容量累加起来,如果直接重新建一条边的话,会因为边太多超时 这个地方的+=我查了几个小时/kk
e[y].push_back(x); //反向边
}
while(bfs()) update();
cout << ans;
return 0;
}