题目链接: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. nyoj814_又见拦截导弹_DP

    又见拦截导弹 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 大家对拦截导弹那个题目应该比较熟悉了,我再叙述一下题意:某国为了防御敌国的导弹袭击,新研制出来一种导弹拦 ...

  2. Match:Blue Jeans(POJ 3080)

    DNA序列 题目大意:给你m串字符串,要你找最长的相同的连续字串 这题暴力kmp即可,注意要按字典序排序,同时,是len<3才输出no significant commonalities #in ...

  3. 在JAVA中如何跳出当前的多重嵌套循环

    可以使用return,但使用return后,会跳出整个函数,多重循环后面的代码无法执行. public static void main(String[] args) { // TODO Auto-g ...

  4. IOS 推送消息 php做推送服务端

    IOS推送消息是许多IOS应用都具备的功能,最近也在研究这个功能,参考了很多资料终于搞定了,下面就把步骤拿出来分享下: iOS消息推送的工作机制可以简单的用下图来概括: Provider是指某个iPh ...

  5. [Android] adb 命令 dumpsys activity , 用来看 task 中的activity。 (uninstall virus)

    用“adb shell dumpsys activity”命令再来查看一下系统运行的的任务,就会看到: ACTIVITY MANAGER ACTIVITIES (dumpsys activity ac ...

  6. July 4th, Week 28th Monday, 2016

    Goals determine what you are going to be. 你的目标决定你将成为怎样的人. What are your goals? What kind of people y ...

  7. 常用js函数整理--common.js

    var h = {}; h.get = function (url, data, ok, error) { $.ajax({ url: url, data: data, dataType: 'json ...

  8. 根据复选框checkbox的选中状态来打开或关闭隐藏层

    HTML:  <input type="checkbox" id="check-expert"> <div id="expert&q ...

  9. 51nod1057(python2计算n!)

    题目链接:www.51nod.com/onlineJudge/questionCode.html#!problemId=1057 思路:直接for循环呗- 代码: n = int( raw_input ...

  10. db2 bind on luw

    https://www.ibm.com/support/knowledgecenter/SSEPGG_10.5.0/com.ibm.db2.luw.apdv.embed.doc/doc/c000556 ...