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. Android Camera系统深入理解

    1. Android Camera系统架构 http://blog.csdn.net/myarrow/article/details/8489674

  2. 在vc6.0下编的对话框界面如果没做过其他处理,往往显的很生硬,怎么样才能使他有Windows XP的风格呢,其实也很简单,我们来看看下面两种方法。

    在vc6.0下编的对话框界面如果没做过其他处理,往往显的很生硬,怎么样才能使他有Windows XP的风格呢,其实也很简单,我们来看看下面两种方法.    方法一: 1.首先确认你在Windows   ...

  3. 中国vs美国制造业公司营业额大排名,看看哪些属于美国制造业的优势产业(中美旗鼓相当,而且还有本土制造的优势)

    当然,所谓的美国制造业,大量的东西现在 在中国制造和生产,但这里列举的,主要是卖实体工业产品为主的美国公司这个榜单里主要列出以工业产品销售为主的公司. 所以各大能源巨头虽然本身也是装备制造大户,但没被 ...

  4. HTTP协议六种请求方法,get,head,put,delete,post有什么区别

    标准Http协议支持六种请求方法,即: 1.GET 2.POST 3.PUT 4.Delete 5.HEAD 6.Options 但其实我们大部分情况下只用到了GET和POST.如果想设计一个符合RE ...

  5. 动态预览Xib的实现

    写一个TestView继承于UIView,然后写个对应的xib,把xib的名字设置成TestView,这是标准的用xib加载这个view必须得条件 然后xib里把这个View的backgroundCo ...

  6. Codeforces Round #106 (Div. 2) D. Coloring Brackets —— 区间DP

    题目链接:https://vjudge.net/problem/CodeForces-149D D. Coloring Brackets time limit per test 2 seconds m ...

  7. RedisCluster集群搭建

    搭建集群方案 安装部署任何一个应用其实都很简单,只要安装步骤一步一步来就行了.下面说一下 Redis 集群搭建规划,由于集群至少需要6个节点(3主3从模式),所以,没有这么多机器给我玩,我本地也起不了 ...

  8. 目录操作(PHP)

    1.创建目录(文件夹)mkdir("./test");2.删除目录(文件夹)只能删除空的文件夹rmdir("./test");3.移动目录(文件夹)rename ...

  9. set STL 简单说说

    set 这个容器,可以排序,以及去掉重复的东西 #include<bits/stdc++.h> using namespace std; int main() { string s; se ...

  10. CodeForces-816B:Karen and Coffee (简单线段树)

    To stay woke and attentive during classes, Karen needs some coffee! Karen, a coffee aficionado, want ...