您的位置:首页 > 理论基础 > 计算机网络

[模板练习]网络最大流

2017-04-20 16:09 295 查看
原题链接

Ford-Fulkerson

从源点开始

往下搜

搜的途中

构建反向边

正向边容量减少

反向变容量增加

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<queue>
#define MAX 99999999
using namespace std;

struct nico
{
int vi,wi,bk;
};

vector<nico> map[10005];

int f,d,flow,n,m,s,t,u,v,w,used[10005];

void add(int ui,int vi,int wi)
{
map[ui].push_back((nico){vi,wi,map[vi].size()});
map[vi].push_back((nico){ui,0,map[ui].size()-1});
}

int dfs(int sr,int tr,int fl)
{
int i;

if(sr==tr) return fl;

for(i=0;i<map[sr].size();i++)
{
nico &tmp=map[sr][i];
if(tmp.wi&&!used[tmp.vi])
{
used[tmp.vi]=1;

d=dfs(tmp.vi,tr,min(tmp.wi,fl));

if(d>0)
{
tmp.wi-=d;
map[tmp.vi][tmp.bk].wi+=d;

return d;
}
}
}

}

int maxflow(int sr,int tr)
{
while(1)
{
memset(used,0,sizeof(used));
f=dfs(sr,tr,MAX);

if(f==0) return flow;
flow+=f;
}
}

int main()
{
int i,ans;

scanf("%d%d%d%d",&n,&m,&s,&t);

for(i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}

ans=maxflow(s,t);

printf("%d",ans);
return 0;
}


EK

大体思路是广搜

搜到每条路

记录路径

流量变成min(当前流量,容量)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<queue>
#define MAX 99999999
using namespace std;

struct nico
{
int to,val,bk;
};

struct maki
{
int p,edge;
}pre[10005];

vector<nico> map[10005];
queue<int> q;
int n,m,s,t,flo[10005],flow,incr;

void add(int from,int to,int val)
{
map[from].push_back((nico){to,val,map[to].size()});
map[to].push_back((nico){from,0,map[from].size()-1});
}

int bfs(int sr,int tr)
{
int i,index;

while(!q.empty())
q.pop();

for(i=1;i<=n;i++)
{
pre[i].p=-1;
pre[i].edge=-1;
}

q.push(sr);
flo[sr]=MAX;
pre[sr].p=0;

while(!q.empty())
{
index=q.front();
q.pop();

if(index==tr) break;

for(i=0;i<map[index].size();i++)
{
nico &tmp=map[index][i];

if(tmp.val&&pre[tmp.to].p==-1)
{
pre[tmp.to].p=index;
pre[tmp.to].edge=i;
flo[tmp.to]=min(tmp.val,flo[index]);
q.push(tmp.to);
}
}
}

if(pre.p==-1) return -1;
return flo;

}

int maxflow(int sr,int tr)
{
int k,last;

incr=bfs(sr,tr);

while(incr!=-1)
{
k=tr;

while(k!=sr)
{
last=pre[k].p;
nico &tmp=map[last][pre[k].edge];

tmp.val-=incr;
map[k][tmp.bk].val+=incr;

k=last;
}

flow+=incr;
incr=bfs(sr,tr);
}

return flow;
}

int main()
{
int i,ans,ui,vi,wi;

scanf("%d%d%d%d",&n,&m,&s,&t);

for(i=1;i<=m;i++)
{
scanf("%d%d%d",&ui,&vi,&wi);
add(ui,vi,wi);
}

ans=maxflow(s,t);

printf("%d",ans);
return 0;
}


Dinic

多加了个深度

把上面的板子拼一拼

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<queue>
#define MAX 99999999
using namespace std;

struct nico
{
int to,val,bk;
};

queue<int> q;
vector<nico> map[10005];
int n,m,s,t,dep[10005],flow;

void add(int from,int to,int val)
{
map[from].push_back((nico){to,val,map[to].size()});
map[to].push_back((nico){from,0,map[from].size()-1});
}

int bfs(int sr,int tr)
{
int i,index;

while(!q.empty())
q.pop();

memset(dep,-1,sizeof(dep));

dep[s]=0;
q.push(s);

while(!q.empty())
{
index=q.front();
q.pop();

for(i=0;i<map[index].size();i++)
{
nico &tmp=map[index][i];

if(dep[tmp.to]==-1&&tmp.val)
{
dep[tmp.to]=dep[index]+1;
q.push(tmp.to);
}
}
}

if(dep[t]!=-1) return dep[t];
return 0;
}

int dfs(int sr,int tr,int fl)
{

int i,re;

if(sr==tr) return fl;

for(i=0;i<map[sr].size();i++)
{
nico &tmp=map[sr][i];

if(dep[tmp.to]==dep[sr]+1&&tmp.val&&(re=dfs(tmp.to,tr,min(fl,tmp.val))))
{
tmp.val-=re;
map[tmp.to][tmp.bk].val+=re;

return re;
}
}

return 0;

}

int dinic(int sr,int tr)
{
int f;

while(bfs(sr,tr))
{
while(1)
{
f=dfs(s,t,MAX);

if(!f) break;

flow+=f;
}
}

return flow;
}

int main()
{
int i,u,v,w,ans;

scanf("%d%d%d%d",&n,&m,&s,&t);

for(i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}

ans=dinic(s,t);
printf("%d",ans);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: