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. xcode4中build Settings常见参数解析

    本文转载至 http://shiminghua234.blog.163.com/blog/static/263912422012411103526386/     1.Installation Dir ...

  2. 【bzoj4554】[Tjoi2016&Heoi2016]游戏

    现在问题有硬石头和软石头的限制 所以要对地图进行预处理 分行做,把有#隔开的*(x)形成联通块的存储下来. 分列作,把有#隔开的*(x)形成联通块的存储下来. 求出所有的行联通个数和列联通个数 作为二 ...

  3. Spring中的IOC容器(学习笔记)

    如何将Bean配置到Spring的Bean容器中 通过xml配置文件: Bean实现类来自第三方类库:如“DataSource”等      需要命名空间配置如:context,aop,mvc等   ...

  4. poj 1015 Jury Compromise(背包+方案输出)

    \(Jury Compromise\) \(solution:\) 这道题很有意思,它的状态设得很...奇怪.但是它的数据范围实在是太暴露了.虽然当时还是想了好久好久,出题人设了几个限制(首先要两个的 ...

  5. MRP-MD04 中的函数

    1.需求溯源 : MD_PEGGING_NODIALOG 2.实时库存 : MD_STOCK_REQUIREMENTS_LIST_API 这个函数中MDPSX 和 MDEZX 是通过 MDPS 的 I ...

  6. RabbitMQ 使用

    安装步骤略过. 启动 启动很简单,找到安装后的 RabbitMQ 所在目录下的 sbin 目录,可以看到该目录下有6个以 rabbitmq 开头的可执行文件,直接执行 rabbitmq-server ...

  7. 编译android内核和文件系统,已经安装jdk,提示build/core/config.mk:268: *** Error: could not find jdk tools.jar

    1:确保安装jdk,如果没有安装请移布:http://www.cnblogs.com/jiuyueguang/p/3156621.html 2:如果已经安装了jdk,还是提示此错误, 解决方法 请确保 ...

  8. HDU3045 Picnic Cows —— 斜率优化DP

    题目链接:https://vjudge.net/problem/HDU-3045 Picnic Cows Time Limit: 8000/4000 MS (Java/Others)    Memor ...

  9. 有关定时器setTimeout()、setInterval()详解

    JavaScript提供定时执行代码的功能,叫做定时器(timer),主要由setTimeout()和setInterval()这两个函数来完成. setTimeout() setTimeout函数用 ...

  10. 书写优雅的shell脚本(四) - kill命令的合理使用

    Linux中的kill命令用来终止指定的进程(terminate a process)的运行,是Linux下进程管理的常用命令.通常,终止一个前台进程可以使用Ctrl+C键,但是,对于一个后台进程就须 ...