只是帮助自己记忆一下。
ISAP应该是一种复杂度比较优秀的最大流算法。
具体优化分为两部分,都是基于dinic之上的。
1.1.1.当前弧优化,这种优化比较显然,就是对于每一次流,每条边一定是只经过一次的,那么这样就可以将每条流过的变在链式前向星中删掉。
2.2.2.进阶版分层图优化。这个现在不是很理解。不过只留dep[u]==dep[v]+1dep[u] == dep[v] + 1dep[u]==dep[v]+1这部分比较显然,不过用gapgapgap优化的每次将dep[u]++dep[u] ++dep[u]++并不是很理解,暂时留个坑,只能感性理解。
#include <cstdio>
#include <queue>
using namespace std;
const int N = 1e4 + 10;
const int M = 1e5 + 10;
const int inf = 1e9 + 7;
struct Edge{
int to,next,val;
} f[M << 1];
int n,m,s,t,gap[N],dep[N],head[N],stu[N],ans,cnt;
queue <int> q;
int read()
{
int x = 0,w = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') w = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
return x * w;
}
int min(int a,int b) {return a < b ? a : b;}
void add(int u,int v,int w)
{
f[++ cnt].to = v;
f[cnt].val = w;
f[cnt].next = stu[u];
stu[u] = cnt;
}
void init()
{
for (int i = 1; i <= n; i ++) head[i] = stu[i];
q.push(t);
gap[dep[t] = 1] = 1;
while (!q.empty())
{
int u = q.front();
q.pop();
for (int i = head[u]; i; i = f[i].next)
if (!dep[f[i].to])
++ gap[dep[f[i].to] = dep[u] + 1],q.push(f[i].to);
}
}
int flo(int u,int mi)
{
if (u == t) return mi;
int flow = 0;
for (int &i = head[u]; i; i = f[i].next)
if (dep[u] == dep[f[i].to] + 1)
{
int res = flo(f[i].to,min(mi,f[i].val));
flow += res;
mi -= res;
f[i].val -= res;
f[i ^ 1].val += res;
if (!mi) return flow;
}
if (!(-- gap[dep[u]])) dep[s] = n + 1;
++ gap[++ dep[u]],head[u] = stu[u];
return flow;
}
int ISAP()
{
init();
int res = flo(s,inf);
while (dep[s] <= n) res += flo(s,inf);
return res;
}
int main()
{
cnt = 1;
n = read(),m = read(),s = read(),t = read();
for (int i = 1,u,v,w; i <= m; i ++)
u = read(),v = read(),w = read(),add(u,v,w),add(v,u,0);
printf("%d\n",ISAP());
return 0;
}