您的位置:首页 > 其它

hdu1532最大流EK与SAP算法

2013-04-30 20:36 183 查看
EK是最朴素的最大流算法了,但效率比较慢,当然代码也比较清晰,思路去看LRJ的白书就行了。

但是由于网上大牛总结SAP基本上是解决最大流的最标准模板了,

网上大牛说基本没有什么最大流能卡SAP。

EK代码:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N = 210;   //小规模   不用考虑效率
#define INF  1<<20
int f

;int r

;int c

;
int a
;int q
;int p
;
int main()
{
int sum,s,n,m,b,t,x,v,k;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(c,0,sizeof(c));
memset(f,0,sizeof(f));
for(int i=0;i<n;i++)
{
scanf("%d%d%d",&x,&b,&t);
c[x][b]+=t;            //注意该题有重边
}
sum=0;

while(1)
{
s=1; int top=0;int last=0;
memset(p,0,sizeof(p));
memset(a,0,sizeof(a));
memset(q,0,sizeof(q));
a[s]=INF;
q[top++]=s;
while(top>last)
{
int u=q[last++];
for(int v=1;v<=m;v++)
{
if(!a[v]&&c[u][v]>f[u][v])
{
p[v]=u;q[top++]=v;             //记录v的父亲,加入队列
a[v]=a[u]<c[u][v]-f[u][v]?a[u]:c[u][v]-f[u][v];        //最小残量
}
}
}
if(!a[m])  break;    //若没有更新  说明已经不存在增广路
for(k=m;k!=s;k=p[k])
{
f[p[k]][k]+=a[m];
f[k][p[k]]+=a[m];
}
sum+=a[m];
}
printf("%d\n",sum);
}
return 0;
}


SAP模板:

#include<cstdio>
#include<cstring>
using namespace std;

const int maxn = 220;
const int inf = 10000000;//不要开太大
int c[maxn][maxn];
int q[maxn], pre[maxn];
int level[maxn], gap[maxn];
int n, m;
int s, t;
void init_sap(){
memset(level,  1, sizeof (level));
//printf("---    %d\n", level[2]);
//for(int i = 0; i <= n; i ++) level[i] =  n + 310;
memset(gap, 0, sizeof gap);
memset(pre, -1, sizeof pre);
int qs = 0, qe = 0;
q[qe++] = t;
level[t] = 0;
gap[ level[t] ] ++;
while(qs < qe){
int hd = q[qs++];
for(int i = 1; i <= n; i ++){
if(level[i] > n && c[i][hd] > 0){//level[i] >= n  也可以,why ?
q[qe++] = i;
level[i] = level[hd] + 1;
gap[ level[i] ] ++;
}
}
}
}
int find_path(int u){
for(int i = 1; i <= n; i ++)
if(c[u][i] > 0 && level[u] == level[i] + 1) return i;
return -1;
}
int relabel(int u){
int tmp = inf;
for(int i = 1; i <= n; i ++)
if(c[u][i] > 0 && tmp > level[i] + 1)
tmp = level[i] + 1;
if(tmp == inf) tmp = n;
return tmp;
}
int sap(){
init_sap();
int flow = 0, u = s;
while(level[s] <= n){
int v = find_path(u);
if(v > 0){
pre[v] = u;
u = v;
if(u == t){
int min_flow = inf;
for(int i = t; i != s; i = pre[i])
if(min_flow > c[ pre[i]][i])
min_flow = c[ pre[i]][i];
for(int i = t; i != s; i = pre[i]){
c[pre[i]][i] -= min_flow;
c[i][pre[i]] += min_flow;
}
flow += min_flow;
u = s;
}
}else{
if(-- gap[ level[u]] == 0) return flow;
int v = relabel(u);
gap[v] ++;
level[u] = v;
if(u != s) u = pre[u];
}
}
return flow;
}
int main(){
while(~scanf("%d%d", &m, &n)){
memset(c, 0, sizeof c);
for(int i = 1; i <= m; i ++){
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
c[u][v] += w;
}
s = 1, t = n;
int flow = sap();
printf("%d\n", flow);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: