EK算法
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+50;
int head[maxn],ecnt=1,pre[maxn],vis[maxn];
int n,m,s,t;
long long ans,dis[maxn];
int flag[2505][2505];
struct mint
{
int nxt,v;
long long w;
}e[maxn];
inline void addline(int u,int v,long long w)
{
e[++ecnt].nxt=head[u];
e[ecnt].v=v;
e[ecnt].w=w;
head[u]=ecnt;
e[++ecnt].nxt=head[v];
e[ecnt].v=u;
e[ecnt].w=0;
head[v]=ecnt;
}
inline int bfs()
{
memset(vis,0,sizeof(vis));
queue<int> q;
q.push(s);
vis[s]=1;
dis[s]=2005020600;//初始化
while(!q.empty())
{
int now=q.front();
q.pop();
for(int i=head[now];i;i=e[i].nxt)
{
if(e[i].w==0) continue;//该边不位于残量网络中,故不经过
int v=e[i].v;
if(vis[v]==1) continue;//不去往一个已经到过的点
dis[v]=min(dis[now],e[i].w);//维护增广路的可行流量(即增广路上所有边的流量最小值)
pre[v]=i;//将边i存入增广路中(pre[v]维护终点为v的一条在增广路上的边)
q.push(v);//将v加入队列,继续bfs
vis[v]=1;//把v标记为已被经过
if(v==t) return 1;//如果到达汇点,则说明存在一条可行的增广路,直接返回1,结束bfs
}
}
return 0;
}
inline void update()
{
int x=t;//从汇点向源点更新边的流量信息
while(x!=s)//到达汇点即停止(以为一条增广路至多经过源点一次)
{
int v=pre[x];
e[v].w-=dis[t];
e[v^1].w+=dis[t];
x=e[v^1].v;
}//修改将每条增广路上的边的流量
ans+=dis[t];//修改最终答案
}
int main()
{
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=1;i<=m;++i)
{
int u,v;
long long w;
scanf("%d%d%lld",&u,&v,&w);
if(flag[u][v]==0)
{
addline(u,v,w);
flag[u][v]=ecnt;
}
else
{
e[flag[u][v]-1].w+=w;
}
}
while(bfs()!=0)
{
update();
}
printf("%lld",ans);
return 0;
}
Dinic算法
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+50;
const long long INF=2e18;
int n,m,s,t,ecnt=1;
int dis[maxn],head[maxn];
int flag[2505][2505];
long long ans=0;
struct mint
{
int nxt,v;
long long w;
}e[maxn<<1];
inline void addline(int u,int v,long long w)
{
e[++ecnt].nxt=head[u];
e[ecnt].v=v;
e[ecnt].w=w;
head[u]=ecnt;
e[++ecnt].nxt=head[v];
e[ecnt].v=u;
e[ecnt].w=0;
head[v]=ecnt;
}
int BFS()
{
queue<int> q;
memset(dis,-1,sizeof(dis));//每次寻找增广路径都需要将dis数组重置
dis[s]=0;
q.push(s);
while(!q.empty())
{
int now=q.front();
q.pop();
for(int i=head[now];i;i=e[i].nxt)
{
if(e[i].w==0) continue;
int v=e[i].v;
if(dis[v]!=-1) continue;
dis[v]=dis[now]+1;
q.push(v);
}
}
if(dis[t]!=-1) return 1; //汇点值不为-1,说明增广路径存在
else return 0; //反之不存在
}
int DFS(int now,long long MAX) //point为当前遍历的节点,MAX为最大可行流量,MAX初始为INF
{
long long a;
if(now==t) return MAX; //当前点为汇点时返回即可
for(int i=head[now];i;i=e[i].nxt)
{
if(e[i].w==0) continue;
int v=e[i].v;
if(dis[v]!=dis[now]+1) continue;
a=DFS(v,min(MAX,e[i].w));
if(a==0) continue;
e[i].w-=a;
e[i^1].w+=a;
return a;
}
return 0;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=1;i<=m;++i)
{
int u,v;
long long w;
scanf("%d%d%lld",&u,&v,&w);
if(flag[u][v]==0)
{
addline(u,v,w);
flag[u][v]=ecnt;
}
else
{
e[flag[u][v]-1].w+=w;
}
}
while(BFS()!=0) //当增广路径存在进行DFS
{
long long add=DFS(s,INF); //从源点出发,初始最大可行流设为无穷大
ans+=add; //结果加上得到的最大可行流
}
printf("%lld",ans);
return 0;
}