题目链接:http://poj.org/problem?id=1273

a.EK算法:(Edmond-Karp): 用BFS不断找增广路径,当找不到增广路径时当前流量即为最大流。

b.dinic算法:不断找最短路。

题意:现在有m个池塘(从1到m开始编号,1为源点,m为汇点),及n条水渠,给出这n条水渠所连接的池塘和所能流过的水量,求水渠中所能流过的水的最大容量.

//http://blog.csdn.net/huzhengnan/article/details/7766446一个写的特别好的博客,包括好几种求最大流的写法;

EK(Edmonds_Karp):不断找增广路径,当找不到增广路径时当前流量即为最大流。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
#define INF 0xfffffff int F[][],C[][];
int a[],p[];
int n,m,sum; void EK()
{
queue<int>q;//BFS找增广路
while()
{
memset(a,,sizeof(a));
q.push();//原点入队
a[]=INF;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int v=; v<=m; v++)
{
if(!a[v] && C[u][v]-F[u][v]>)
{
p[v]=u;
q.push(v);
a[v]=min(a[u],C[u][v]-F[u][v]);
}
}
}
if(a[m]==)
break; /找不到增广路,则当前流即为最大流
sum+=a[m];
for(int i=m; i!=; i=p[i])
{
F[p[i]][i]+=a[m];
F[i][p[i]]-=a[m];
}
}
printf("%d\n",sum);
} int main()
{
int x,y,z;
while(scanf("%d%d",&n,&m)==)
{
memset(F,,sizeof(F));
memset(C,,sizeof(C));
memset(p,-,sizeof(p));
sum=;//记录最大流
while(n--)
{
scanf("%d%d%d",&x,&y,&z);
C[x][y]+=z;//可能会有相同边
}
EK();
}
return ;
}

flow[u][v]为<u,v>流量,cap[u][v]为<u,v>容量 
a[i]表示源点s到节点i路径上的最小残留量、p[i]记录i的前驱。

反向弧的作用:
意义:前的流到a的流量,来退掉一些以往流到a的流量,是这些被退掉的流量能够通过别的路径到达汇点。
//俗话说,就是原来走3,现在走1我不在你那走了,我在你那少走点吗,能在别人那走更多。起到退回的作用,非常好理解!

空间优化的EK:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
#define INF 0xfffffff int C[][];
int a[],p[];
int n,m,sum; void EK()
{
queue<int>q;
while()
{
memset(a,,sizeof(a));
a[]=INF;
q.push();
while(!q.empty())
{
int u=q.front();
q.pop();
for(int v=; v<=m; v++)
{
if(!a[v] && C[u][v]>)
{
p[v]=u;
q.push(v);
a[v]=min(a[u],C[u][v]);
}
}
}
if(a[m]==) break;
sum+=a[m];
for(int i=m; i!=; i=p[i])
{
C[p[i]][i]-=a[m];
C[i][p[i]]+=a[m];
}
}
printf("%d\n",sum);
} int main()
{
int x,y,z;
while(scanf("%d%d",&n,&m)==)
{
sum=;
memset(C,,sizeof(C));
memset(p,-,sizeof(p));
while(n--)
{
scanf("%d%d%d",&x,&y,&z);
C[x][y]+=z;
}
EK();
}
return ;
} //省掉了一个flow数组。

dinic:            https://comzyh.com/blog/archives/568/#Dinic-Code

邻接矩阵实现:

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define INF 0xfffffff int C[][];
int dis[];
int q[],h,r;
int n,m,sum; int BFS()
{
memset(dis,-,sizeof(dis));
dis[]=;
h=;
r=;
q[]=;
while(h<r)
{
int j=q[++h];
for(int i=; i<=m; i++)
{
if(dis[i]< && C[j][i]>) //如果没有被访问过 并且两点之间“联通”
{
dis[i]=dis[j]+;//那么到原点的距离就加一
q[++r]=i;//队列中的第几个元素是谁
}
}
}
if(dis[m]>) return ; //如果可以找到原点到汇点的通路 那么即找到增广路 返回1
else return ; //汇点的DIS小于零,表明BFS不到汇点
} //Find代表一次增广,函数返回本次增广的流量,返回0表示无法增广
int Find(int x,int low) //找到最小的流量
{
int a=;
if(x==m) return low; //如果当前点是汇点,返回当前增加的流量
for(int i=; i<=m; i++)
if(C[x][i]> && dis[i]==dis[x]+ && (a=Find(i,min(low,C[x][i])) ) )
{
//联通 是分成图的下一层 能到汇点
C[x][i]-=a;
C[i][x]+=a;
return a;
}
return ;
} int main()
{
int x,y,z,ans;
while(scanf("%d%d",&n,&m)==)
{
memset(C,,sizeof(C));
while(n--)
{
scanf("%d%d%d",&x,&y,&z);
C[x][y]+=z;
}
sum=;
while(BFS())//成功建立分图
while(ans=Find(,INF))//成功找到增广路经
sum+=ans;
printf("%d\n",sum);
}
return ;
}

dinic邻接表实现:

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std; #define MAXN 210
#define INF 0xfffffff struct Edge
{
int st, ed;
int c;
int next;
} edge[MAXN << ]; int n, m;
int s, t;
int ans;
int e = ;
int head[MAXN];
int d[MAXN]; void init()
{
int i,j;
int a,b,c;
s=;
t=m;
e=;
ans=;
memset(head,- sizeof(head));
for(i=; i<=n;i++)
{
scanf("%d%d%d",&a,&b,&c);
edge[e].st=a;
edge[e].ed=b;
edge[e].c=c;
edge[e].next=head[a];
head[a]=e++;
edge[e].st=b;
edge[e].ed=a;
edge[e].next=head[b];
head[b]=e++;
}
} int bfs()
{
memset(d,-,sizeof(d));
queue<int> q;
d[s]=;
q.push(s);
int i;
int cur;
while(!q.empty())
{
cur=q.front();
q.pop();
for(i=head[cur]; i!=-; i=edge[i].next)
{
if(d[edge[i].ed]==- && edge[i].c > )
{
d[edge[i].ed]=d[cur] + ;
q.push(edge[i].ed);
}
}
}
if(d[t]<) return ;
return ;
} int dinic(int x, int flow)
{
if(x==t) return flow; int i,a;
for(i=head[x]; i!=-; i=edge[i].next)
{
if(d[edge[i].ed]==d[x]+ && edge[i].c> && (a=dinic(edge[i].ed, min(flow,edge[i].c))))
{
edge[i].c-=a;
edge[i^].c+=a;
return a;
}
}
return ;
} void solve()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
while(bfs())
{
int increment;
increment=dinic(, INF);
ans+=increment;
}
printf("%d\n",ans);
}
} int main()
{
#ifdef LOCAL
#endif
solve();
return ;
}

SAP有个优化就是 当出现断链时,就可以直接退出,还有个优化是当前弧的优化,这两个优化只需要一句话+一个数组就解决了,相当实惠,好的ISAP执行的效率真的非常高,这个写的ISAP用的是链式前向星法表示。  http://blog.csdn.net/shiqi_614/article/details/7982858(相关博客)

SPFA优化:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define MAXN 500
#define MAXE 40000
#define INF 0x7fffffff
long ne,nv,tmp,s,t,index;
struct Edge
{
long next,pair;
long v,cap,flow;
} edge[MAXE];
long net[MAXN];
long ISAP()
{
long numb[MAXN],dist[MAXN],curedge[MAXN],pre[MAXN];
long cur_flow,max_flow,u,tmp,neck,i;
memset(dist,,sizeof(dist));
memset(numb,,sizeof(numb));
memset(pre,-,sizeof(pre));
for(i=; i<=nv ; i++)
curedge[i]=net[i];
numb[nv]=nv;
max_flow=;
u=s;
while(dist[s]<nv)
{
if(u==t)
{
cur_flow=INF;
for(i=s; i!=t; i=edge[curedge[i]].v)
{
if(cur_flow>edge[curedge[i]].cap)
{
neck=i;
cur_flow=edge[curedge[i]].cap;
}
}
for(i=s; i!=t; i=edge[curedge[i]].v)
{
tmp=curedge[i];
edge[tmp].cap-=cur_flow;
edge[tmp].flow+=cur_flow;
tmp=edge[tmp].pair;
edge[tmp].cap+=cur_flow;
edge[tmp].flow-=cur_flow;
}
max_flow+=cur_flow;
u=neck;
}
for(i=curedge[u]; i!=-; i=edge[i].next)
if(edge[i].cap> && dist[u]==dist[edge[i].v]+)
break;
if(i!=-)
{
curedge[u]=i;
pre[edge[i].v]=u;
u=edge[i].v;
}
else
{
if(==--numb[dist[u]]) break;
curedge[u]=net[u];
for(tmp=nv,i=net[u]; i!=-; i=edge[i].next)
if(edge[i].cap>)
tmp=tmp<dist[edge[i].v]?tmp:dist[edge[i].v];
dist[u]=tmp+;
++numb[dist[u]];
if(u!=s) u=pre[u];
}
} return max_flow;
}
int main()
{
long i,j,np,nc,m,n;
long a,b,val;
long g[MAXN][MAXN];
while(scanf("%d%d",&ne,&nv)!=EOF)
{
s=;
t=nv;
memset(g,,sizeof(g));
memset(net,-,sizeof(net));
for(i=; i<ne; i++)
{
scanf("%ld%ld%ld",&a,&b,&val);
g[a][b]+=val;
}
for(i=; i<=nv; ++i)
for(j=i; j<=nv; j++)
if(g[i][j]||g[j][i])
{
edge[index].next=net[i];
edge[index].v=j;
edge[index].cap=g[i][j];
edge[index].flow=;
edge[index].pair=index+;
net[i]=index++;
edge[index].next=net[j];
edge[index].v=i;
edge[index].cap=g[j][i];
edge[index].flow=;
edge[index].pair=index-;
net[j]=index++;
}
printf("%ld\n",ISAP());
}
return ;
}

poj 1273 最大流的更多相关文章

  1. UVA 820 --- POJ 1273 最大流

    找了好久这两个的区别...UVA820 WA了 好多次.不过以后就做模板了,可以求任意两点之间的最大流. UVA 是无向图,因此可能有重边,POJ 1273是有向图,而且是单源点求最大流,因此改模板的 ...

  2. [转载 ]POJ 1273 最大流模板

    转载 百度文库花了5分下的 不过确实是自己需要的东西经典的最大流题POJ1273 ——其他练习题 POJ3436 . 题意描述: 现在有m个池塘(从1到m开始编号,1为源点,m为汇点),及n条水渠,给 ...

  3. poj 1273最大流dinic算法模板

    #include<stdio.h> #include<string.h> #define N 300 #define inf 0x7fffffff #include<qu ...

  4. poj 1273 最大流入门

    明天再拍一遍 #include <iostream> #include <queue> using namespace std; ; const int INF = 0x7FF ...

  5. POJ 1273 Drainage Ditches(网络流dinic算法模板)

    POJ 1273给出M条边,N个点,求源点1到汇点N的最大流量. 本文主要就是附上dinic的模板,供以后参考. #include <iostream> #include <stdi ...

  6. poj 3281 最大流+建图

    很巧妙的思想 转自:http://www.cnblogs.com/kuangbin/archive/2012/08/21/2649850.html 本题能够想到用最大流做,那真的是太绝了.建模的方法很 ...

  7. poj 1273 Drainage Ditches 最大流入门题

    题目链接:http://poj.org/problem?id=1273 Every time it rains on Farmer John's fields, a pond forms over B ...

  8. poj 1273 Drainage Ditches(最大流)

    http://poj.org/problem?id=1273 Drainage Ditches Time Limit: 1000MS   Memory Limit: 10000K Total Subm ...

  9. POJ 1273 - Drainage Ditches - [最大流模板题] - [EK算法模板][Dinic算法模板 - 邻接表型]

    题目链接:http://poj.org/problem?id=1273 Time Limit: 1000MS Memory Limit: 10000K Description Every time i ...

随机推荐

  1. 在微信浏览器中如何让他自动关闭当前页面回到会话框js

    <script type="text/javascript"> wx.config(jssdkconfig); require(['jquery', 'util'], ...

  2. Servlet题库

    一.    填空题 Servlet中使用Session对象的步骤为:调用  HttpServletRequest.getSession()  得到Session对象,查看Session对象,在会话中保 ...

  3. August 13th 2016 Week 33rd Saturday

    What makes life dreary is the want of motive. 没有目标与动力,生活便会郁闷无光. Without dreams and hope, there will ...

  4. !struct operator reload

    struct t3DObject //对象信息结构体{ int numOfVerts; // 模型中顶点的数目 int numOfFaces; // 模型中面的数目 int numTexVertex; ...

  5. 三、jQuery--jQuery基础--jQuery基础课程--第4章 jQuery表单选择器

    1.:input表单选择器 如何获取表单全部元素?:input表单选择器可以实现,它的功能是返回全部的表单元素,不仅包括所有<input>标记的表单元素,而且还包括<textarea ...

  6. MyEclipse破解(MEGen.java)

    步骤: 1.将MEGen.java粘贴到任意web项目下,运行结果如下: 2.输入注册名:如sun,得到注册码: 3.Window  >>  Preference  >>  S ...

  7. html+css学习笔记:实用LessColor函数搭建配色方案

    http://www.zcool.com.cn/article/ZMTUyNDc2.html 前言:用LESS CSS框架进行编码会简化代码结构,提高我们的工作效率,但是试验后你会发现,默认情况下,L ...

  8. jQuery each用法及each解析json

    $(function(){ $("button").click( function(){ var a1=""; var a2=""; var ...

  9. EF – 8.多对多关联

    5.6.10 <多对多关联(上)> 时长:9分57秒 难度:难 5.6.11<多对多关联(下)> 时长:8分50秒 难度:难 如果单独地把多对多关联的CRUD拿出来讲,确实比较 ...

  10. App 开发:Hybrid 架构下的 HTML5 应用加速方案

    在移动 App 开发领域,主流的开发模式可分为 Native.Hybrid.WebApp 三种方式.然而 2013 年,纯 WebApp 开发模式的发展受到一定挫折,以 Facebook 为代表的独立 ...