POJ 1273 - Drainage Ditches - [最大流模板题] - [EK算法模板][Dinic算法模板 - 邻接表型]
题目链接:http://poj.org/problem?id=1273
Description
Farmer John knows not only how many gallons of water each ditch can transport per minute but also the exact layout of the ditches, which feed out of the pond and into each other and stream in a potentially complex network.
Given all this information, determine the maximum rate at which water can be transported out of the pond and into the stream. For any given ditch, water flows in only one direction, but there might be a way that water can flow in a circle.
Input
Output
Sample Input
5 4
1 2 40
1 4 20
2 4 20
2 3 30
3 4 10
Sample Output
50
Source
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#define MAX 203
#define INF 0x3f3f3f3f
using namespace std;
int n,m;//n条边,m个点
struct Edge{
int u,v,c,f;
};
struct EdmondsKarp{
vector<Edge> E;
vector<int> G[MAX];
int aug[MAX];//源点到i的可增广量
int pre[MAX];//记录当前路径中点i的入弧编号
void init(int n)
{
E.clear();
for(int i=;i<n;i++) G[i].clear();
}
void addedge(int from,int to,int cap)
{
E.push_back((Edge){from,to,cap,});
E.push_back((Edge){to,from,,});
G[from].push_back(E.size()-);
G[to].push_back(E.size()-);
}
int maxflow(int s,int t)
{
int flow=;
while()
{
memset(aug,,sizeof(aug));
queue<int> q;
q.push(s);
aug[s]=INF;
while(!q.empty())
{
int now=q.front(); q.pop();
for(int i=;i<G[now].size();i++)
{
Edge edge=E[G[now][i]];
if(!aug[edge.v] && edge.c>edge.f)
{
pre[edge.v]=G[now][i];
aug[edge.v]=min(aug[now],edge.c-edge.f);
q.push(edge.v);
}
}
if(aug[t]) break;
}
if(!aug[t]) break;
for(int i=t;i!=s;i=E[(pre[i])].u)
{
E[pre[i]].f+=aug[t];
E[pre[i]^].f-=aug[t];
}
flow+=aug[t];
}
return flow;
}
}EK;
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
EK.init(m);
for(int from,to,cap,i=;i<=n;i++)
{
scanf("%d%d%d",&from,&to,&cap);
EK.addedge(from,to,cap);
}
printf("%d\n",EK.maxflow(,m));
}
}
注:
①代码第51行:“if(aug[t]) break;”语句,由于我们一次BFS只找到一条增广路径,所以aug[]数组每次BFS之前都进行初始化为零,因此一旦aug[t]不为零,那么必然我们已经找到了一条增广路径,这是就没必要继续进行BFS,直接跳出循环,节省时间。
②代码第53行:“if(!aug[t]) break;”语句,这是在BFS循环外的判断语句,因为若是当我们进行完一遍BFS,未找到一条增广路径,那么根据最大流最小割定理,当前已经是最大流情况,所以立即跳出即可。
最大流最小割定理:

嗯,然后再补一个Dinic算法版的:
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#define MAX 203
#define INF 0x3f3f3f3f
using namespace std;
int n,m;//n条边,m个点
struct Dinic
{
struct Edge{
int u,v,c,f;
};
int s,t;
vector<Edge> E;
vector<int> G[MAX];
bool vis[MAX]; //BFS使用
int lev[MAX];//记录层次
int cur[MAX]; //当前弧下标
void init(int n)
{
E.clear();
for(int i=;i<n;i++) G[i].clear();
}
void addedge(int from,int to,int cap)
{
E.push_back((Edge){from,to,cap,});
E.push_back((Edge){to,from,,});
G[from].push_back(E.size()-);
G[to].push_back(E.size()-);
}
bool bfs()
{
memset(vis,,sizeof(vis));
queue<int> q;
q.push(s);
lev[s]=;
vis[s]=;
while(!q.empty())
{
int now=q.front(); q.pop();
for(int i=,_size=G[now].size();i<_size;i++)
{
Edge edge=E[G[now][i]];
int nex=edge.v;
if(!vis[nex] && edge.c>edge.f)//属于残存网络的边
{
lev[nex]=lev[now]+;
q.push(nex);
vis[nex]=;
}
}
}
return vis[t];
}
int dfs(int now,int aug)//now表示当前结点,aug表示目前为止的最小残量
{
if(now==t || aug==) return aug;//aug等于0时及时退出,此时相当于断路了
int flow=,f;
for(int& i=cur[now],_size=G[now].size();i<_size;i++)//从上次考虑的弧开始,注意要使用引用,同时修改cur[now]
{
Edge& edge=E[G[now][i]];
int nex=edge.v;
if(lev[now]+ == lev[nex] && (f=dfs(nex,min(aug,edge.c-edge.f)))>)
{
edge.f+=f;
E[G[now][i]^].f-=f;
flow+=f;
aug-=f;
if(!aug) break;//aug等于0及时退出,当aug!=0,说明当前节点还存在另一个增广路分支
}
}
return flow;
}
int maxflow(int s,int t)//主过程
{
int flow=;
while(bfs())//不停地用bfs构造分层网络,然后用dfs沿着阻塞流增广
{
memset(cur,,sizeof(cur));
flow+=dfs(s,INF);
}
return flow;
}
}dinic;
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
dinic.init(m);
for(int from,to,cap,i=;i<=n;i++)
{
scanf("%d%d%d",&from,&to,&cap);
dinic.addedge(from,to,cap);
}
dinic.s=, dinic.t=m;
printf("%d\n",dinic.maxflow(,m));
}
}
具体Dinic算法是个什么操作可以参见:王欣上《浅谈基于分层思想的网络流算法》.pdf
模板:
#include<cstring>
#include<vector>
#include<queue>
#define MAX 100
#define INF 0x3f3f3f3f
struct Edge{
int u,v,c,f;
};
struct Dinic
{
int s,t;
vector<Edge> E;
vector<int> G[MAX];
bool vis[MAX];
int lev[MAX];
int cur[MAX];
void init(int l,int r)
{
E.clear();
for(int i=l;i<=r;i++) G[i].clear();
}
void addedge(int from,int to,int cap)
{
E.push_back((Edge){from,to,cap,});
E.push_back((Edge){to,from,,});
int m=E.size();
G[from].push_back(m-);
G[to].push_back(m-);
}
bool bfs()
{
memset(vis,,sizeof(vis));
queue<int> q;
q.push(s);
lev[s]=;
vis[s]=;
while(!q.empty())
{
int now=q.front(); q.pop();
for(int i=,_size=G[now].size();i<_size;i++)
{
Edge edge=E[G[now][i]];
int nex=edge.v;
if(!vis[nex] && edge.c>edge.f)
{
lev[nex]=lev[now]+;
q.push(nex);
vis[nex]=;
}
}
}
return vis[t];
}
int dfs(int now,int aug)
{
if(now==t || aug==) return aug;
int flow=,f;
for(int& i=cur[now],_size=G[now].size();i<_size;i++)
{
Edge& edge=E[G[now][i]];
int nex=edge.v;
if(lev[now]+ == lev[nex] && (f=dfs(nex,min(aug,edge.c-edge.f)))>)
{
edge.f+=f;
E[G[now][i]^].f-=f;
flow+=f;
aug-=f;
if(!aug) break;
}
}
return flow;
}
int maxflow()
{
int flow=;
while(bfs())
{
memset(cur,,sizeof(cur));
flow+=dfs(s,INF);
}
return flow;
}
}dinic;
POJ 1273 - Drainage Ditches - [最大流模板题] - [EK算法模板][Dinic算法模板 - 邻接表型]的更多相关文章
- 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(最大流 Edmonds-Karp )
题目链接:poj1273 Drainage Ditches 呜呜,今天自学网络流,看了EK算法,学的晕晕的,留个简单模板题来作纪念... #include<cstdio> #include ...
- POJ 1273 Drainage Ditches | 最大流模板
#include<cstdio> #include<algorithm> #include<cstring> #include<queue> #defi ...
- POJ 1273 Drainage Ditches(最大流Dinic 模板)
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n, ...
- POJ 1273 Drainage Ditches 最大流
这道题用dinic会超时 用E_K就没问题 注意输入数据有重边.POJ1273 dinic的复杂度为O(N*N*M)E_K的复杂度为O(N*M*M)对于这道题,复杂度是相同的. 然而dinic主要依靠 ...
- poj 1273 Drainage Ditches(最大流)
http://poj.org/problem?id=1273 Drainage Ditches Time Limit: 1000MS Memory Limit: 10000K Total Subm ...
- POJ 1273 Drainage Ditches (网络最大流)
http://poj.org/problem? id=1273 Drainage Ditches Time Limit: 1000MS Memory Limit: 10000K Total Sub ...
- POJ 1273 Drainage Ditches(网络流dinic算法模板)
POJ 1273给出M条边,N个点,求源点1到汇点N的最大流量. 本文主要就是附上dinic的模板,供以后参考. #include <iostream> #include <stdi ...
- 网络流最经典的入门题 各种网络流算法都能AC。 poj 1273 Drainage Ditches
Drainage Ditches 题目抽象:给你m条边u,v,c. n个定点,源点1,汇点n.求最大流. 最好的入门题,各种算法都可以拿来练习 (1): 一般增广路算法 ford() #in ...
随机推荐
- hibernate4.3 无法获取数据库最新值
在用ssh框架的时候遇到一个问题(hibernate版本号4.3) 问题描写叙述:web端和应用程序都能够读写数据库.当应用程序改动数据库后.hibernate无法读取最新值,读出来的一直都是旧数据. ...
- Java -- 新IO -- 目录
20.1 Java 新IO简介 20.2 缓冲区与Buffer 例:演示缓冲区的操作流程 Class : IntBufferDemo01 20.2.2 深入缓冲区操作 20.2.3 创建子缓冲区 20 ...
- Maven发布war包到Tomcat
一.修改Tomcat下配置文件tomcat-users.xml,然后启动 <role rolename="manager-gui"/> <role rolenam ...
- 【RF库Collections测试】Reverse List
Name:Reverse ListSource:Collections <test library>Arguments:[ list_ ]Reverses the given list i ...
- 第一个map reduce程序
完成了第一个mapReduce例子,记录一下. 实验环境: hadoop在三台ubuntu机器上部署 开发在window7上进行 hadoop版本2.2.0 下载了hadoop-eclipse-plu ...
- Nginx 用户认证
访问一些比较私密的页面 ( 如管理后台,数据后台 ) 时,我们就可以设置访问该页面时需要使用用户名和密码进行验证,这就是用户认证 [root@localhost ~]$ cat /usr/local/ ...
- Selenium 选项卡管理
什么是选项卡: from selenium import webdriver browser = webdriver.Chrome() browser.get("http://www.bai ...
- AESDK开发之UI消息响应
UI创建: 在该入口下 case PF_Cmd_PARAMS_SETUP: //.... break; 必须在末尾指定UI数目,UI数目一般是枚举,如果和枚举长度不一致也会报错.所以最好是直接修改枚举 ...
- [NodeJS] Node.js 与 V8 的故事
要说Node.js的历史,就不得不说说V8历史.在此之前我们先一句话描述一下什么是Node.js:Node.js是一个基于Google Chrome V8 Javascript引擎之上的平台,用以创建 ...
- mybatis 之resultType="HashMap" parameterType="list"
<!-- 查询商品仓库信息 --> <select id="loadGoodsStock" resultType="HashMap" para ...