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

网络流三种算法及比较

2016-08-25 18:23 288 查看
核心代码

(1)EK 算法

复杂度O(V*E*E)

#define N 204
int c

;//边容量
int f

;//边实际流量
int pre
;//记录增广路径
int res
;//残余网络
queue<int> qq;
void init(){
while(!qq.empty())qq.pop();
memset(c,0,sizeof(c));
memset(f,0,sizeof(f));
}
int EK(int s,int t){
int i,j;
int ans=0;
while(1){
memset(res,0,sizeof(res));
res[s] = MAX;//源点的残留网络要置为无限大!否则下面找增广路出错
pre[s] = -1;
qq.push(s);
//bfs找增广路径
while(!qq.empty()){
int x = qq.front();
qq.pop();
for(i=1;i<=t;i++){
if(!res[i] && f[x][i] < c[x][i]){
qq.push(i);
pre[i] = x;
res[i] = min(c[x][i] - f[x][i], res[x]);//这里类似dp,如果有增广路,那么res[t]就是增广路的最小权
}
}
}
if(res[t]==0)break;//找不到增广路就退出
int k = t;
while(pre[k]!=-1){
f[pre[k]][k] += res[t];//正向边加上新的流量
f[k][pre[k]] -= res[t];//反向边要减去新的流量,反向边的作用是给程序一个后悔的机会
k = pre[k];
}
ans += res[t];
}
return ans;
}


(2)Dinic递归

#define M 400
struct node {
int u, v, next, cap;
} edge[M*M];
int next[M], head[M], layer[M], Q[M * 2], mark[M];
int ecnt;
void init(){
ecnt= 0;
memset(head,-1,sizeof(head));
}
void add(int u, int v, int c) {
edge[ecnt].u = u;
edge[ecnt].v = v;
edge[ecnt].cap = c;
edge[ecnt].next = head[u];
head[u] = ecnt++;
edge[ecnt].u = v;
edge[ecnt].v = u;
edge[ecnt].cap = 0;
edge[ecnt].next = head[v];
head[v] = ecnt++;
}
bool BFS(int begin, int end) {
int i, l, h, k, y;
for (i = 0; i <= end; i++) layer[i] = -1;
layer[begin] = 0;
l = h = 0;
Q[l++] = begin;
while (h < l) {
k = Q[h++];
for (i = head[k]; i != -1; i = edge[i].next) {
y = edge[i].v;
if (edge[i].cap > 0 && layer[y] == -1) {
layer[y] = layer[k] + 1;
if (y == end)
return true;
Q[l++] = y;
}
}
}
return false;
}

int DFS(int x, int exp, int end) {
mark[x] = 1;
if (x == end)return exp;
int y, temp, i;
for (i = next[x]; i != -1; i = edge[i].next, next[x] = i) {
y = edge[i].v;
if (edge[i].cap > 0 && layer[y] == layer[x] + 1 && !mark[y]) {
if ((temp = (DFS(y, min(exp, edge[i].cap), end))) > 0) {
edge[i].cap -= temp;//流完后正向流表示剩余流量
edge[i^1].cap += temp;//流完后反向流表示正向流的流量
return temp;
}
}
}
return 0;
}

int Dinic_flow(int begin, int end) {
int i, ans = 0, flow;
while (BFS(begin, end)) {
for (i = 0; i <= end; i++)next[i] = head[i];
while (true) {
for (i = 0; i <= end; i++) mark[i] = 0;
flow = DFS(begin, INT_MAX, end);
if (flow == 0)break;
ans += flow;
}
}
return ans;
}


(3)SAP算法

const int MAXN=20010;
const int MAXM=500010;
int n,m;//n为点数 m为边数
int h[MAXN];
int gap[MAXN];
int p[MAXN],ecnt;
int source,sink;
struct edge{
int v;//边的下一点
int next;//下一条边的编号
int val;//边权值
}e[MAXM];
inline void init(){memset(p,-1,sizeof(p));eid=0;
//有向
inline void insert1(int from,int to,int val){
e[ecnt].v=to;
e[ecnt].val=val;
e[ecnt].next=p[from];
p[from]=eid++;
swap(from,to);
e[ecnt].v=to;
e[ecnt].val=0;
e[ecnt].next=p[from];
p[from]=eid++;
}
//无向
inline void insert2(int from,int to,int val){
e[ecnt].v=to;
e[ecnt].val=val;
e[ecnt].next=p[from];
p[from]=eid++;
swap(from,to);
e[ecnt].v=to;
e[ecnt].val=val;
e[ecnt].next=p[from];
p[from]=eid++;
}
inline int dfs(int pos,int cost){
if (pos==sink){
return cost;
}
int j,minh=n-1,lv=cost,d;
for (j=p[pos];j!=-1;j=e[j].next){
int v=e[j].v,val=e[j].val;
if(val>0){
if (h[v]+1==h[pos]){
if (lv<e[j].val) d=lv;
else d=e[j].val;
d=dfs(v,d);
e[j].val-=d;
e[j^1].val+=d;
lv-=d;
if (h[source]>=n) return cost-lv;
if (lv==0) break;
}

if (h[v]<minh)  minh=h[v];
}
}
if (lv==cost){
--gap[h[pos]];
if (gap[h[pos]]==0) h[source]=n;
h[pos]=minh+1;
++gap[h[pos]];
}
return cost-lv;
}
int sap(int st,int ed){

source=st;
sink=ed;
int ans=0;
memset(gap,0,sizeof(gap));
memset(h,0,sizeof(h));
gap[st]=n;
while (h[st]<n){
ans+=dfs(st,INT_MAX);
}
return ans;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 c语言 网络 流量