Edmonds_Karp算法模板
邻接矩阵形式
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N=205;
const int INF=0x3f3f3f3f;
int g[N][N];
int pre[N];//路径上每个结点的前驱结点
bool vis[N];
int n,m;//m是顶点数目,顶点编号从1开始 1是源,m是汇,n是边数
int EdmondsKarp()
{
int i,v;
queue<int>q;
memset(pre,-1,sizeof(-1));
memset(vis,0,sizeof(vis));
pre[1]=0;
vis[1]=1;
q.push(1);
bool flag=false;//标记bfs是否寻找到一条源到汇的可行路径
while(!q.empty()){
v=q.front();
q.pop();
for(int i=1;i<=m;i++)
if(g[v][i]>0&&vis[i]==0){//必须是依然有容量的边,才可以走
pre[i]=v;
vis[i]=1;
if(i==m){
flag=true;
break;
}
else
q.push(i);
}
}
if(!flag)//找不到就退出
return 0;
int ans=INF;
v=m;
//寻找源到汇路径上容量最小的边,其容量就是此次增加的总流量
while(pre[v]){
ans=min(ans,g[pre[v]][v]);
v=pre[v];
}
//沿此路径添加反向边,同时修改路径上每条边的容量
v=m;
while(pre[v]){
g[pre[v]][v]-=ans;
g[v][pre[v]]+=ans;
v=pre[v];
}
return ans;
}
int main()
{
while(cin>>n>>m){//m是顶点数目,顶点编号从1开始
int s,e,c;
memset(g,0,sizeof(g));
for(int i=1;i<=n;i++){
cin>>s>>e>>c;
g[s][e]+=c;//两点之间可能有多条边
}
int ans=0,tmp;
while(tmp=EdmondsKarp())
ans+=tmp;
cout<<ans<<endl;
}
return 0;
}
邻接表形式(前向星实现)
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=4005;
const int INF=0x3f3f3f3f;
//前向星实现图的邻接表
int M,head[N];
struct Edge{
int next,to,w;
}edge[N];
void add(int from,int to,int w)
{
edge[M].next=head[from];
edge[M].to=to;
edge[M].w=w;
head[from]=M++;
}
struct Pre{
int u,id;
}pre[N];
bool vis[N];
int n,m;
int EdmondsKarp()
{
queue<int>q;
memset(vis,false,sizeof(vis));
vis[1]=true;
q.push(1);
bool flag=false;
int u,v,w;
//寻找从源到汇的一条增广路径
while(!q.empty())
{
u=q.front();
q.pop();
for(int k=head[u];k!=-1;k=edge[k].next)
{
v=edge[k].to;
w=edge[k].w;
if(w>0&&!vis[v])//必须是依然有容量的边,才可以走
{
pre[v].u=u;//记录v的前驱结点
pre[v].id=k;//记录 u->v的边号
vis[v]=true;
if(v==n)
{
flag=true;//找到一条增广路径
break;
}
else
q.push(v);
}
}
}
if(!flag)//找不到就退出
return 0;
int ans=INF;
//寻找源到汇路径上容量最小的边,其容量就是此次增加的总流量
for(v=n;v!=1;v=pre[v].u)
ans=min(ans,edge[pre[v].id].w);
//沿此路径添加反向边,同时修改路径上每条边的容量
for(v=n;v!=1;v=pre[v].u)
{
edge[pre[v].id].w-=ans;
edge[(pre[v].id)^1].w+=ans;// (pre[v].id)^1是编号为 pre[v].id的反向边编号
}
return ans;
}
int main()
{
while(~scanf("%d%d",&m,&n))
{
int from,to,w;
M=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&from,&to,&w);
add(from,to,w);
add(to,from,0);//添加反向边
}
int ans=0,temp;
while(temp=EdmondsKarp())
ans+=temp;
printf("%d\n",ans);
}
return 0;
}