Problem Description

Network flow is a well-known difficult problem for ACMers. Given a graph, your task is to find out the maximum flow for the weighted directed graph.

Input

The first line of input contains an integer T, denoting the number of test cases.
For each test case, the first line contains two integers N and M, denoting the number of vertexes and edges in the graph. (2 <= N <= 15, 0 <= M <= 1000)
Next M lines, each line contains three integers X, Y and C, there is an edge from X to Y and the capacity of it is C. (1 <= X, Y <= N, 1 <= C <= 1000)

Output

For each test cases, you should output the maximum flow from source 1 to sink N.

Sample Input

2
3 2
1 2 1
2 3 1
3 3
1 2 1
2 3 1
1 3 1

Sample Output

Case 1: 1
Case 2: 2
解题思路:Dicic实现,即每个阶段先进行1次bfs给图分层,然后在该图上进行1次或多次寻找增广路,如果当前层次图中已找不到增广路,就重新给图分层,然后继续找增广路,只要t的level小于0就说明当前网络已达到最大流。时间复杂度大概为O(|E||V|2)。
AC代码一(312ms):
 #include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=;//int cnt=1;
struct edge{ int to, cap; size_t rev;
edge(int _to, int _cap, size_t _rev) :to(_to), cap(_cap), rev(_rev){}//构造函数,初始化结构体变量
};//指向节点to,边容量是cap,rev是记录为当前邻接点to反向边的编号
vector<edge> G[maxn];//邻接表,G[i][j]表示节点i连接的第j条边包含的所有信息
int t,n,m,x,y,c,level[maxn];//level数组在bfs时为分层图所用
void add_edge(int from,int to,int cap){//向图中增加一条从s到t容量为cap的边
G[from].push_back(edge( to, cap, G[to].size() ));
G[to].push_back(edge( from, , G[from].size() - ));//关键:反向建边,初始流量为0
}
//bfs给图分层次
void bfs(int s){
memset(level,-,sizeof(level));//刚开始每个节点的层次置为-1
queue<int> que;//队列实现bfs
level[s]=;//源点s为第0层
que.push(s);
while(!que.empty()){//给图分层
int v=que.front();que.pop();
for(size_t i=;i<G[v].size();++i){//遍历节点v与之相连的每条边
edge &e=G[v][i];//取出与节点v相连的第i条边
if(e.cap>&&level[e.to]<){//如果边残余流量大于0,且节点e.to还未分层
level[e.to]=level[v]+;//节点e.to的层次为指向它的节点v所在层次数加1
que.push(e.to);
}
}
}
}
//dfs寻找增广路,寻找当前图中s-->t的一条增广路
int dfs(int v,int t,int f){//v->t(t为汇点),当前增广路径上的最小剩余流量为f
if(v==t)return f;//到达汇点t
for(size_t i=;i<G[v].size();++i){//遍历节点v与之相连的每条边
edge &e=G[v][i];//取出与节点v相连的第i条边
if(e.cap> && level[v]<level[e.to]){//如果该边残流量大于0,且邻接点e.to是v的下一级,就增广下去
//cout<<"当前遍历到的点v:"<<v<<",邻接点to:"<<e.to<<endl;
int d=dfs(e.to,t,min(f,e.cap));//维护当前增广路上最小的剩余流量f
if(d>){//若f>0,说明找到了一条增广路
//cout<<v<<"-->"<<e.to<<",边容量为:"<<e.cap<<endl;
e.cap-=d;//正向边流量减去f
G[e.to][e.rev].cap+=d;//反向边流量加上f
return d;//沿着增广路回溯到源点s,不会在途中去深搜其他点,返回当前增广路上的最小剩余流量
}
}
}
return ;//否则说明没有增广路,返回0
}
//Dinic算法实现最大流,每个阶段执行完一次bfs分层之后,只需查找当前层次图中是否还增广路即可
int max_flow(int s,int t){
int flow=;
while(){
bfs(s);//每个阶段先bfs将图分层标记
if(level[t]<)return flow;
//如果分层之后,汇点t的层次小于0,即未被分层,说明再无增广路,则直接返回当前最大流量
int f=dfs(s,t,INF);
//cout<<"第"<<cnt++<<"次的最小剩余容量为:"<<f<<endl;
while(f>){//在该层次图中找到增广路
flow+=f;//累加到最大流中
f=dfs(s,t,INF);//继续找该层次图中是否还有增广路,直到f为0,
//cout<<"第"<<cnt++<<"次的最小剩余容量为:"<<f<<endl;
}
}
}
int main(){
while(~scanf("%d",&t)){
for(int cas=;cas<=t;++cas){
scanf("%d%d",&n,&m);//cnt=1;
for(int i=;i<=n;++i)G[i].clear();
while(m--){
scanf("%d%d%d",&x,&y,&c);
add_edge(x,y,c);
}
printf("Case %d: %d\n",cas,max_flow(,n));
}
}
return ;
}

AC代码二(93ms):当前弧优化Dinic算法。

 #include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=;
struct edge{ int to,cap;size_t rev;
edge(int _to, int _cap, size_t _rev):to(_to),cap(_cap),rev(_rev){}
};
int T,n,m,x,y,c,level[maxn];queue<int> que;vector<edge> G[maxn];size_t curfir[maxn];
void add_edge(int from,int to,int cap){
G[from].push_back(edge(to,cap,G[to].size()));
G[to].push_back(edge(from,,G[from].size()-));
}
bool bfs(int s,int t){
memset(level,-,sizeof(level));
while(!que.empty())que.pop();
level[s]=;
que.push(s);
while(!que.empty()){
int v=que.front();que.pop();
for(size_t i=;i<G[v].size();++i){
edge &e=G[v][i];
if(e.cap>&&level[e.to]<){
level[e.to]=level[v]+;
que.push(e.to);
}
}
}
return level[t]<?false:true;
}
int dfs(int v,int t,int f){
if(v==t)return f;
for(size_t &i=curfir[v];i<G[v].size();++i){
edge &e=G[v][i];
if(e.cap>&&(level[v]+==level[e.to])){
int d=dfs(e.to,t,min(f,e.cap));
if(d>){
e.cap-=d;
G[e.to][e.rev].cap+=d;
return d;
}
}
}
return ;
}
int max_flow(int s,int t){
int f,flow=;
while(bfs(s,t)){
memset(curfir,,sizeof(curfir));
while((f=dfs(s,t,INF))>)flow+=f;
}
return flow;
}
int main(){
while(~scanf("%d",&T)){
for(int cas=;cas<=T;++cas){
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i)G[i].clear();
while(m--){
scanf("%d%d%d",&x,&y,&c);
add_edge(x,y,c);
}
printf("Case %d: %d\n",cas,max_flow(,n));
}
}
return ;
}

题解报告:hdu 3549 Flow Problem(最大流入门)的更多相关文章

  1. HDU 3549 Flow Problem(最大流)

    HDU 3549 Flow Problem(最大流) Time Limit: 5000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/ ...

  2. 网络流 HDU 3549 Flow Problem

    网络流 HDU 3549 Flow Problem 题目:pid=3549">http://acm.hdu.edu.cn/showproblem.php?pid=3549 用增广路算法 ...

  3. hdu 3549 Flow Problem

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=3549 Flow Problem Description Network flow is a well- ...

  4. hdu 3549 Flow Problem【最大流增广路入门模板题】

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=3549 Flow Problem Time Limit: 5000/5000 MS (Java/Others ...

  5. hdu 3549 Flow Problem (网络最大流)

    Flow Problem Time Limit: 5000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Tota ...

  6. hdu 3549 Flow Problem Edmonds_Karp算法求解最大流

    Flow Problem 题意:N个顶点M条边,(2 <= N <= 15, 0 <= M <= 1000)问从1到N的最大流量为多少? 分析:直接使用Edmonds_Karp ...

  7. HDU 3549 Flow Problem 网络流(最大流) FF EK

    Flow Problem Time Limit: 5000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Tot ...

  8. HDU 3549 Flow Problem (最大流ISAP)

    Flow Problem Time Limit: 5000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Tota ...

  9. hdu 3549 Flow Problem (Dinic)

    Flow ProblemTime Limit: 5000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total ...

  10. hdu 3549 Flow Problem 最大流问题 (模板题)

    Flow Problem Time Limit: 5000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Tota ...

随机推荐

  1. Redis+EJB实现缓存(一)

        上篇博客大概的对Redis做了一个主要的了解.由于刚刚接触自己也不太明确.所以上篇博客写的乱七八糟的.这篇由于项目须要,学习了一下Redis和EJB集成. 如今脑子相对照较清晰了一些. 实现思 ...

  2. app发布流程

    在app上架之前做两件事(instruments,profile): 1.代码静态分析:不用运行程序,直接检测代码有没有潜在的一些内存泄漏 2.动态分析:a l loctions/leaks 内存溢出 ...

  3. axis、xfire、CXF 、JWS

    1.JWS是Java语言对WebService服务的一种实现,用来开发和发布服务.而从服务本身的角度来看JWS服务是没有语言界限的.但是Java语言为Java开发者提供便捷发布和调用WebServic ...

  4. 20170218-取值Domain

    1.通过视图DD07V, 例子:取SD 凭证类别的DOMAIN(VBTYP)DATA: LT_DD07V TYPE TABLE OF DD07V.SELECT * INTO T_DD07V FROM ...

  5. PM12条

    PM首先是用户 站在用户角度看待问题 用户体验是一个完整的过程 追求效果,不做没用的东西 发现需求,而不是创造需求 决定不做什么,往往比决定做什么更重要 用户是很难被教育的,要迎合用户,而不是改变用户 ...

  6. Uva 3902 Network

    题目大意: 在非叶子节点上安装最少的服务器使得,每个叶子节点到服务器的距离不超过k. 贪心+图上的dfs. 先从深度最大的叶子节点开始找.找到父节点后再用这个父节点进行扩充. /* ********* ...

  7. 用Delphi7 调用.NET 2.0的WebService 所要注意的问题(Document格式和UTF8编码)

    Delphi7 调用VS.NET 2005开发的基于.NET 2.0的WebService时发生了错误.查阅资料 http://www.community.borland.com/article/bo ...

  8. (linux)块设备驱动程序

      1.4.1  Linux块设备驱动程序原理(1) 顾名思义,块设备驱动程序就是支持以块的方式进行读写的设备.块设备和字符设备最大的区别在于读写数据的基本单元不同.块设备读写数据的基本单元为块,例如 ...

  9. axios基于常见业务场景的二次封装

    axios axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中.在前端框架中的应用也是特别广泛,不管是vue还是react,都有很多项目用axios作为网络 ...

  10. jconsole工具检测堆内存变化的使用

    jconsole将Java写的程序检测. 从Java 5开始 引入了 JConsole.JConsole 是一个内置 Java 性能分析器,可以从命令行或在 GUI shell 中运行.您可以轻松地使 ...