poj 1273 最大流
题目链接: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 最大流的更多相关文章
- UVA 820 --- POJ 1273 最大流
找了好久这两个的区别...UVA820 WA了 好多次.不过以后就做模板了,可以求任意两点之间的最大流. UVA 是无向图,因此可能有重边,POJ 1273是有向图,而且是单源点求最大流,因此改模板的 ...
- [转载 ]POJ 1273 最大流模板
转载 百度文库花了5分下的 不过确实是自己需要的东西经典的最大流题POJ1273 ——其他练习题 POJ3436 . 题意描述: 现在有m个池塘(从1到m开始编号,1为源点,m为汇点),及n条水渠,给 ...
- poj 1273最大流dinic算法模板
#include<stdio.h> #include<string.h> #define N 300 #define inf 0x7fffffff #include<qu ...
- poj 1273 最大流入门
明天再拍一遍 #include <iostream> #include <queue> using namespace std; ; const int INF = 0x7FF ...
- POJ 1273 Drainage Ditches(网络流dinic算法模板)
POJ 1273给出M条边,N个点,求源点1到汇点N的最大流量. 本文主要就是附上dinic的模板,供以后参考. #include <iostream> #include <stdi ...
- poj 3281 最大流+建图
很巧妙的思想 转自:http://www.cnblogs.com/kuangbin/archive/2012/08/21/2649850.html 本题能够想到用最大流做,那真的是太绝了.建模的方法很 ...
- poj 1273 Drainage Ditches 最大流入门题
题目链接:http://poj.org/problem?id=1273 Every time it rains on Farmer John's fields, a pond forms over B ...
- poj 1273 Drainage Ditches(最大流)
http://poj.org/problem?id=1273 Drainage Ditches Time Limit: 1000MS Memory Limit: 10000K Total Subm ...
- POJ 1273 - Drainage Ditches - [最大流模板题] - [EK算法模板][Dinic算法模板 - 邻接表型]
题目链接:http://poj.org/problem?id=1273 Time Limit: 1000MS Memory Limit: 10000K Description Every time i ...
随机推荐
- Mathematics:Dead Fraction(POJ 1930)
消失了的分式 题目大意:某个人在赶论文,需要把里面有些写成小数的数字化为分式,这些小数是无限循环小数(有理数),要你找对应的分母最小的那个分式(也就是从哪里开始循环并不知道). 一开始我也是蒙了,这尼 ...
- storyboard在ios模拟器无法显示的问题
一.问题描述 1.在原有项目新建一个名称为test的storyboard类型的文件. 2.test.storyboard添加View Controller,并设置View Controller下Vie ...
- UVA 10815 Andy's First Dictionary ---set
题目链接 题意:输入一个文本,找出所有不同的单词(连续的字母序列),按字典序从小到大输出.单词不区分大小写. 刘汝佳算法竞赛入门经典(第二版)P112 #include <iostream> ...
- UUID UDID
Google搜索关键字Difference between UUID and UDID,在stackoverflow看见解释,我翻译过来,如下所述. UUID(Universally Unique I ...
- WEB前端开发学习:源码canvas 雪
WEB前端开发学习:源码canvas 雪 双旦节要到了,程序员们为了响应气氛,特别用代码制作了动态雪花,WEB前端开发学习的初学者们一起跟着案例做一遍吧! <!DOCTYPE html> ...
- 阿里云服务器出现Warning: Cannot modify header information - headers already sent by (output started at 问题的解决方法
阿里云服务器出现Warning: Cannot modify header information - headers already sent by (output started at 问题的解决 ...
- 关于内存管理/set/get方法
MRC状态下 1 任何继承NSObject的对象,存放于堆控件中,都需要手动管理内存 .2 基本数据类型放到栈中,对象放到堆空间中,内存是有系统管理的.(int\float\enum\struct) ...
- Android WebView 支持H5的定位Js
//启用数据库 webSettings.setDatabaseEnabled(true); String dir = this.getApplicationContext().getDir(" ...
- EmguCV学习 与opencv的区别和联系
openCV是因特尔的一个开源的视觉库,里面几乎包含了所有的图像处理的经典算法,并且采用C和少量的C++编写,运行效率很高,对于做图像处理这方面工作的,认识opencv是必须的工作.不过opencv有 ...
- MVC - 19.Log4net
下载地址:http://pan.baidu.com/s/1gdxQegN 对于网站来讲,我们不能将异常信息显示给用户, Log4Net用来记录日志,可以将程序运行过程中的信息输出到文件,数据库中等 ...