EK算法模板 算法复杂度 n*m*m (n为点数,m为边数) 源点 1, 汇点 n。
const int maxn=310,inf=0x7fffffff;
int pre[maxn],mat[maxn][maxn];
bool vis[maxn];
int n,m;
int Augment(){
int v;
bool fnd=false;
memset(pre,0,sizeof(pre));
memset(vis,false,sizeof(vis));
pre[1]=0;
vis[1]=1;
deque<int>q;
q.push_back(1);
while(!q.empty()){
v=q.front();
q.pop_front();
for (int i=1;i<=m;i++){
if(mat[v][i]>0&&!vis[i]){ //找到能走且为未走过的边
vis[i]=1;
pre[i]=v;
if(i==m){
fnd=1;
q.clear();
break;
}
else q.push_back(i);
}
}
}
if(!fnd) return 0;
v=m;
int mi=inf;
while(pre[v]){
mi=min(mi,mat[pre[v]][v]);
v=pre[v];
}
v=m;
while(pre[v]){
mat[pre[v]][v]-=mi;
mat[v][pre[v]]+=mi;
v=pre[v];
}
return mi;
}
例题 Poj 1273 Drainage Ditches
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <functional>
#include <queue>
#include <iostream>
using namespace std;
const int maxn=310,inf=0x7fffffff;
int pre[maxn],mat[maxn][maxn];
bool vis[maxn];
int n,m;
int Augment(){
int v;
bool fnd=false;
memset(pre,0,sizeof(pre));
memset(vis,false,sizeof(vis));
pre[1]=0;
vis[1]=1;
deque<int>q;
q.push_back(1);
while(!q.empty()){
v=q.front();
q.pop_front();
for (int i=1;i<=m;i++){
if(mat[v][i]>0&&!vis[i]){
vis[i]=1;
pre[i]=v;
if(i==m){
fnd=1;
q.clear();
break;
}
else q.push_back(i);
}
}
}
if(!fnd) return 0;
v=m;
int mi=inf;
while(pre[v]){
mi=min(mi,mat[pre[v]][v]);
v=pre[v];
}
v=m;
while(pre[v]){
mat[pre[v]][v]-=mi;
mat[v][pre[v]]+=mi;
v=pre[v];
}
return mi;
}
int main(){
while(cin>>n>>m){
memset(mat,0,sizeof(mat));
int u,v,c;
while(n--){
cin>>u>>v>>c;
mat[u][v]+=c;
}
int ans=0,aug;
while(aug=Augment()){
ans+=aug;
}
cout<<ans<<endl;
}
return 0;
}
dinic 算法
时间复杂度 O(n*n*e) (推荐)
struct node{
int u,v,next,c;
}edge[maxn<<1];
int head[maxn];
int cnt,dis[maxn],n,m,ans;
void init(){
memset(head,-1,sizeof(head));
cnt=0;
memset(dis,-1,sizeof(dis));
ans=0;
}
void add(int a,int b,int c){
edge[cnt].u=a;
edge[cnt].v=b;
edge[cnt].c=c;
edge[cnt].next=head[a];
head[a]=cnt++;
}
bool bfs(){
memset(dis,-1,sizeof(dis));
queue<int>q;
dis[1]=0;
q.push(1);
int i,cur;
while(!q.empty()) {
cur=q.front();
q.pop();
for (int i=head[cur];i!=-1;i=edge[i].next){
if(dis[edge[i].v]==-1&&edge[i].c>0){
dis[edge[i].v]=dis[cur]+1;
q.push(edge[i].v);
}
}
}
if(dis[m]<0) return 0;
return 1;
}
int fnd(int x,int low){
int a;
if(x==m) return low;
for (int i=head[x];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(dis[v]==dis[x]+1&&edge[i].c>0&&(a=fnd(v,min(low,edge[i].c)))){
edge[i].c-=a;
edge[i^1].c+=a;
return a;
}
}
return 0;
}
void Dinic(){
int temp;
while(bfs()){
temp=fnd(1,inf);
ans+=temp;
}
printf("%d\n",ans);
}
各种优化:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define inf 0x3f3f3f3f3f3f3f3f
#define ll long long
#define MAXN 10005
using namespace std;
int n,m;//点数、边数
int sp,tp;//原点、汇点
struct node
{
int v,next;
ll cap;
}mp[MAXN*10];
int pre[MAXN],dis[MAXN],cur[MAXN];//cur为当前弧优化,dis存储分层图中每个点的层数(即到原点的最短距离),pre建邻接表
int cnt=0;
void init()//不要忘记初始化
{
cnt=0;
memset(pre,-1,sizeof(pre));
}
void add(int u,int v,int w)//加边
{
mp[cnt].v=v;
mp[cnt].cap=w;
mp[cnt].next=pre[u];
pre[u]=cnt++;
}
bool bfs()//建分层图
{
memset(dis,-1,sizeof(dis));
queue<int>q;
while(!q.empty())
q.pop();
q.push(sp);
dis[sp]=0;
int u,v;
while(!q.empty())
{
u=q.front();
q.pop();
for(int i=pre[u];i!=-1;i=mp[i].next)
{
v=mp[i].v;
if(dis[v]==-1&&mp[i].cap>0)
{
dis[v]=dis[u]+1;
q.push(v);
if(v==tp)
break;
}
}
}
return dis[tp]!=-1;
}
ll dfs(int u,ll cap)//寻找增广路
{
if(u==tp||cap==0)
return cap;
ll res=0,f;
for(int &i=cur[u];i!=-1;i=mp[i].next)
{
int v=mp[i].v;
if(dis[v]==dis[u]+1&&(f=dfs(v,min(cap-res,mp[i].cap)))>0)
{
mp[i].cap-=f;
mp[i^1].cap+=f;
res+=f;
if(res==cap)
return cap;
}
}
if(!res)
dis[u]=-1;
return res;
}
ll dinic()
{
ll ans=0;
while(bfs())
{
for(int i=1;i<=n;i++)
cur[i]=pre[i];
ans+=dfs(sp,inf);
}
return ans;
}
int main()
{
return 0;
}
当前弧优化的dinic
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <functional>
#include <queue>
#include <vector>
using namespace std;
const int maxn=1e5+10,inf=0x7fffffff;
int n,m,f,e,s,t;
struct Edge{
int u,v,c,flow;
Edge(int a,int b,int cc,int f):u(a),v(b),c(cc),flow(f){}
};
struct Dinic{
int s,t;
vector<Edge>edges;
vector<int>pre[maxn];
bool vis[maxn];
int dis[maxn];
int cur[maxn];
void init(){
for (int i=0;i<=n+1;i++)
pre[i].clear();
edges.clear();
}
void AddEdge(int a,int b,int c){
edges.push_back(Edge(a,b,c,0));
edges.push_back(Edge(b,a,0,0));
int mm=edges.size();
pre[a].push_back(mm-2);
pre[b].push_back(mm-1);
}
bool bfs(){
memset(vis,false,sizeof(vis));
queue<int>q;
q.push(s);
vis[s]=1;
dis[s]=0;
while(!q.empty()){
int x=q.front();q.pop();
for (int i=0;i<pre[x].size();i++){
Edge &e=edges[pre[x][i]];
if(!vis[e.v]&& e.c>e.flow){
dis[e.v]=dis[x]+1;
vis[e.v]=1;
q.push(e.v);
}
}
}
return vis[t];
}
int dfs(int x,int cap){
if(x==t||cap==0) return cap;
int f,flow=0;
for (int &i=cur[x];i<pre[x].size();i++){
cur[x]=i;
Edge &e=edges[pre[x][i]];
if(dis[e.v]==dis[x]+1 && (f=dfs(e.v,min(cap,e.c-e.flow)))){
e.flow+=f;
edges[pre[x][i]^1].flow-=f;
flow+=f;
cap-=f;
if(cap==0) break;
}
}
return flow;
}
int Maxflow(int s,int t){
this->s=s;
this->t=t;
int flow=0;
while(bfs()) {
memset(cur,0,sizeof(cur));
flow+=dfs(s,inf);
}
return flow;
}
}dc;
POj 1273
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <functional>
#include <queue>
#include <iostream>
using namespace std;
const int maxn=310,inf=0x7fffffff;
struct node{
int u,v,next,c;
}edge[maxn<<1];
int head[maxn];
int cnt,dis[maxn],n,m,ans;
void init(){
memset(head,-1,sizeof(head));
cnt=0;
memset(dis,-1,sizeof(dis));
ans=0;
}
void add(int a,int b,int c){
edge[cnt].u=a;
edge[cnt].v=b;
edge[cnt].c=c;
edge[cnt].next=head[a];
head[a]=cnt++;
}
bool bfs(){
memset(dis,-1,sizeof(dis));
queue<int>q;
dis[1]=0;
q.push(1);
int i,cur;
while(!q.empty()) {
cur=q.front();
q.pop();
for (int i=head[cur];i!=-1;i=edge[i].next){
if(dis[edge[i].v]==-1&&edge[i].c>0){
dis[edge[i].v]=dis[cur]+1;
q.push(edge[i].v);
}
}
}
if(dis[m]<0) return 0;
return 1;
}
int fnd(int x,int low){
int a;
if(x==m) return low;
for (int i=head[x];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(dis[v]==dis[x]+1&&edge[i].c>0&&(a=fnd(v,min(low,edge[i].c)))){
edge[i].c-=a;
edge[i^1].c+=a;
return a;
}
}
return 0;
}
void Dinic(){
int temp;
while(bfs()){
temp=fnd(1,inf);
ans+=temp;
}
printf("%d\n",ans);
}
int main(){
while(scanf("%d%d",&n,&m)==2){
int a,b,f;
init();
for (int i=1;i<=n;i++){
scanf("%d%d%d",&a,&b,&f);
add(a,b,f);
add(b,a,0);
}
Dinic();
}
return 0;
}
参考博客:
https://blog.csdn.net/lxy767087094/article/details/53606891
https://blog.csdn.net/hitwhacmer1/article/details/47019789
http://acm.pku.edu.cn/summerschool/gw_netflow.pdf
http://www.cnblogs.com/jianrenfang/p/7253715.html