网络流之最大流
EK算法(SAP)
基于增广路的算法,复杂度为 O ( V ∗ E 2 ) O(V*E^2) O(V∗E2)
找了好久网上的板子,感觉比kuangbin的好理解一些,以后就留着自己用蜡
int g[maxn][maxn];//容量
int f[maxn][maxn];//流量
int pre[maxn];
bool vis[maxn];
bool bfs(int sx,int ex)
{
mem(pre,-1);
mem(vis,false);
queue<int> q;
vis[sx]=true;
q.push(sx);
while(!q.empty())
{
int u=q.front();
q.pop();
rep(i,1,n)
{
if (!vis[i]&&g[u][i]>0)
{
vis[i]=true;
pre[i]=u;
if (i==ex)return true;
q.push(i);
}
}
}
return false;
}
int solve(int sx,int ex)//sx为起点,ex为终点
{
int maxflow=0,u,d;
while(bfs(sx,ex))
{
u=ex;
d=INF;
while(u!=sx)
{
d=min(d,g[pre[u]][u]);
u=pre[u];
}
maxflow+=d;
u=ex;
while(u!=sx)
{
g[pre[u]][u]-=d;
g[u][pre[u]]+=d;
if (f[u][pre[u]]>0)f[u][pre[u]]-=d;
else f[pre[u]][u]+=d;
u=pre[u];
}
}
return maxflow;
}
例题1:POJ1273
(补充一下:还有一道模板题:HDU3549)
一个最简单的流量网络,问最大流量。
唯一需要注意的是边可能会有重复。
代码:
const int maxn=4e2+7;
const int INF=1e9;
const ll INFF=1e18;
int g[maxn][maxn];//容量
int f[maxn][maxn];//流量
int pre[maxn];
bool vis[maxn];
int n,m,a,b,c;
bool bfs(int sx,int ex)
{
mem(pre,-1);
mem(vis,false);
queue<int> q;
vis[sx]=true;
q.push(sx);
while(!q.empty())
{
int u=q.front();
q.pop();
rep(i,1,n)
{
if (!vis[i]&&g[u][i]>0)
{
vis[i]=true;
pre[i]=u;
if (i==ex)return true;
q.push(i);
}
}
}
return false;
}
int solve(int sx,int ex)
{
int maxflow=0,u,d;
while(bfs(sx,ex))
{
u=ex;
d=INF;
while(u!=sx)
{
d=min(d,g[pre[u]][u]);
u=pre[u];
}
maxflow+=d;
u=ex;
while(u!=sx)
{
g[pre[u]][u]-=d;
g[u][pre[u]]+=d;
if (f[u][pre[u]]>0)f[u][pre[u]]-=d;
else f[pre[u]][u]+=d;
u=pre[u];
}
}
return maxflow;
}
int main()
{
while(~scanf("%d%d",&m,&n))
{
if (n==0&&m==0)break;
mem(f,0);mem(g,0);
rep(i,1,m)
{
scanf("%d%d%d",&a,&b,&c);
g[a][b]+=c;
}
W(solve(1,n));
}
return 0;
}
例题2:POJ1459
题意理解起来真的恶心我吐了
一共有三种形式的东西:
发电站,它不会消耗电能;
用户,它不会产生电能;
最后一种,它既不会产生电也不会消耗电。(当普通结点处理
现在问你最多这个网络能消耗多少的电量。
题解:可以建立一个超级节点n,连往每一个用户,每一个用户和它之间的容量是他消耗的电能
再建立一个超级节点n+1,连往每一个发电站,每一个发电站和它之间的容量是他产生的电能
之前没看清题,结点标号是 [ 0 , n − 1 ] [0,n-1] [0,n−1],一开始建立了一个标号为0的超级节点,就一直错
代码:
const int maxn=2e2+7;
const int INF=1e9;
const ll INFF=1e18;
int g[maxn][maxn];
int f[maxn][maxn];
int pre[maxn];
bool vis[maxn];
int n,np,nc,m,a,b,c;
bool bfs(int sx,int ex)
{
mem(pre,-1);
mem(vis,false);
queue<int> q;
vis[sx]=true;
q.push(sx);
while(!q.empty())
{
int u=q.front();
q.pop();
rep(i,0,n+1)
{
if (!vis[i]&&g[u][i]>0)
{
vis[i]=true;
pre[i]=u;
if (i==ex)return true;
q.push(i);
}
}
}
return false;
}
int solve(int sx,int ex)
{
int maxflow=0,u,d;
while(bfs(sx,ex))
{
u=ex;
d=INF;
while(u!=sx)
{
d=min(d,g[pre[u]][u]);
u=pre[u];
}
maxflow+=d;
u=ex;
while(u!=sx)
{
g[pre[u]][u]-=d;
g[u][pre[u]]+=d;
if (f[u][pre[u]]>0)f[u][pre[u]]-=d;
else f[pre[u]][u]+=d;
u=pre[u];
}
}
return maxflow;
}
int main()
{
while(~scanf("%d%d%d%d",&n,&np,&nc,&m))
{
mem(f,0);mem(g,0);
rep(i,1,m)
{
scanf(" (%d,%d)%d",&a,&b,&c);
if (a==b)continue;
g[a][b]+=c;
}
rep(i,1,np)
{
scanf(" (%d)%d",&a,&b);
g[n][a]+=b;
}
rep(i,1,nc)
{
scanf(" (%d)%d",&a,&b);
g[a][n+1]+=b;
}
W(solve(n,n+1));
}
return 0;
}