题目链接: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 0xfffffffint F[205][205],C[205][205];
int a[205],p[205];
int n,m,sum;void EK()
{queue<int>q;//BFS找增广路while(1){memset(a,0,sizeof(a));q.push(1);//原点入队a[1]=INF;while(!q.empty()){int u=q.front();q.pop();for(int v=1; v<=m; v++){if(!a[v] && C[u][v]-F[u][v]>0){p[v]=u;q.push(v);a[v]=min(a[u],C[u][v]-F[u][v]);}}}if(a[m]==0)break; /找不到增广路,则当前流即为最大流sum+=a[m];for(int i=m; i!=1; 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)==2){memset(F,0,sizeof(F));memset(C,0,sizeof(C));memset(p,-1,sizeof(p));sum=0;//记录最大流while(n--){scanf("%d%d%d",&x,&y,&z);C[x][y]+=z;//可能会有相同边
        }EK();}return 0;
}

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 0xfffffffint C[205][205];
int a[205],p[205];
int n,m,sum;void EK()
{queue<int>q;while(1){memset(a,0,sizeof(a));a[1]=INF;q.push(1);while(!q.empty()){int u=q.front();q.pop();for(int v=1; v<=m; v++){if(!a[v] && C[u][v]>0){p[v]=u;q.push(v);a[v]=min(a[u],C[u][v]);}}}if(a[m]==0) break;sum+=a[m];for(int i=m; i!=1; 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)==2){sum=0;memset(C,0,sizeof(C));memset(p,-1,sizeof(p));while(n--){scanf("%d%d%d",&x,&y,&z);C[x][y]+=z;}EK();}return 0;
}//省掉了一个flow数组。

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

邻接矩阵实现:

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

dinic邻接表实现:

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

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,0,sizeof(dist));memset(numb,0,sizeof(numb));memset(pre,-1,sizeof(pre));for(i=1; i<=nv ; i++)curedge[i]=net[i];numb[nv]=nv;max_flow=0;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!=-1; i=edge[i].next)if(edge[i].cap>0 && dist[u]==dist[edge[i].v]+1)break;if(i!=-1){curedge[u]=i;pre[edge[i].v]=u;u=edge[i].v;}else{if(0==--numb[dist[u]]) break;curedge[u]=net[u];for(tmp=nv,i=net[u]; i!=-1; i=edge[i].next)if(edge[i].cap>0)tmp=tmp<dist[edge[i].v]?tmp:dist[edge[i].v];dist[u]=tmp+1;++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=1;t=nv;memset(g,0,sizeof(g));memset(net,-1,sizeof(net));for(i=0; i<ne; i++){scanf("%ld%ld%ld",&a,&b,&val);g[a][b]+=val;}for(i=1; 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=0;edge[index].pair=index+1;net[i]=index++;edge[index].next=net[j];edge[index].v=i;edge[index].cap=g[j][i];edge[index].flow=0;edge[index].pair=index-1;net[j]=index++;}printf("%ld\n",ISAP());}return 0;
}

转载于:https://www.cnblogs.com/a-clown/p/5917662.html

poj 1273 最大流相关推荐

  1. POJ 1273 Dinic

    题意 传送门 POJ 1273 Drainage Ditches 题解 最大流模板题,使用 DinicDinicDinic 算法求解. #include <algorithm> #incl ...

  2. POJ 1273 (基础最大流) Drainage Ditches

    虽然算法还没有理解透,但以及迫不及待地想要A道题了. 非常裸的最大流,试试lrj的模板练练手. 1 #include <cstdio> 2 #include <cstring> ...

  3. 【POJ - 1273】Drainage Ditches(网络流,最大流,模板)

    题干: 现在有m个池塘(从1到m开始编号,1为源点,m为汇点),及n条水渠,给出这n条水渠所连接的点和所能流过的最大流量,求从源点到汇点能流过的最大流量. Input 输入包括几种情况. 对于每种情况 ...

  4. POJ - 1273 Drainage Ditches(最大流)

    题目链接:点击查看 题目大意:现在一共有n个节点,需要修建m条水渠将池塘的水引入小溪,点1代表池塘,点n代表小溪,每条水渠都有一定的排水能力,问最大的排水效率是多少 题目分析:网络流的模板题,直接套板 ...

  5. 网络流--最大流--POJ 1273 Drainage Ditches

    链接 Description Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clov ...

  6. POJ 1273 Drainage Ditches 最大流

    很裸的最大流问题,不过注意会有重边,o(╯□╰)o,被阴了WA了一发 还有就是要用long long #include <cstdio> #include <cstring> ...

  7. POJ 3532 基尔霍夫电流定律 + 高斯消元

    题意 传送门 POJ 3532 题解 基尔霍夫电流定律(KCLKCLKCL):在集总参数电路中,任一瞬间,流入或流出电路中任一节点的电流代数和恒等于零.若规定流出为正,则流入为负,KCLKCLKCL ...

  8. POJ 1273 Drainage Ditches

    网络流. 题意非常easy.给出单向边,容量. 找最大流.注意重边要加起来.g[u][v].c+=c; 第一次写网络流. 也是第一个网络流的题. 看了两天,理解了之后就唰唰唰的写出来了. 大概可能是E ...

  9. poj 3614(最大流)

    Sunscreen Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6682   Accepted: 2350 Descrip ...

最新文章

  1. 如何破解汽车-快速的速成课程
  2. Eclipse不自动编译 设置后重新编译仍然没有编译
  3. CCommandLineInfo类
  4. TensorFlow交叉熵
  5. 在64位Win7系统中配置jsp开发环境以及一些问题解决方案
  6. 1.django 开发环境搭建
  7. cs go linux游戏吧,玩家分享:让CSGO画面变成舒服的暖色调
  8. python--OS模块,文件系统
  9. 敏捷开发免费管理工具——火星人预览之三:迭代,计划会,分配
  10. mybatis学习与踩坑记录
  11. c# mysql datetime 判断为空 dbnull_转:SqlServer中的datetime类型的空值和c#中的DateTime的空值的研究...
  12. FastSpring.NET V2.05 final 发布[集成Spring.net NHibernate Ajax]
  13. Hexo + Github搭建自己的博客
  14. 应用:Xbox 360无线大屏幕控制器“WP 7”
  15. VMware 10激活码
  16. win7黑苹果双系统隐藏Clover多余启动项
  17. signature=0805b6a4f11b6551d9a746082990b689,Derived certificate based on changing identity
  18. 谈谈对java的理解
  19. Android dp方式的屏幕适配工具使用(Android Studio插件方式)
  20. android粘性广播删除,android 广播机制(2) 粘性广播-Go语言中文社区

热门文章

  1. 启动和停止一个服务,修改服务的启动类型 Start and Stop Service for windows
  2. windows2k服务和进程详解
  3. QR算法的Matlab 程序,三种实现矩阵QR分解的算法与程序
  4. python throw error_Python实用笔记——错误处理
  5. Ansible(二)——基本环境的部署以及常用模块的使用
  6. LVS负载均衡(LVS简介、三种工作模式、十种调度算法)
  7. Final Cut Pro X中如何使音视频片段能够自由拖动
  8. 3项目里面全局用less变量 cli vue_Vue实战14——抽离全局less变量与Vuex持久化、多模块构建...
  9. 想要系统稳定?最好用也最容易理解的指标是.....
  10. 年后复工,逾期升高,策略应该怎么调优