题解报告:hdu 3549 Flow Problem(最大流入门)
Posted acgoto
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解报告:hdu 3549 Flow Problem(最大流入门)相关的知识,希望对你有一定的参考价值。
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)
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实现,即每个阶段先进行一次bfs给图分层,然后再在该图上进行1次或多次寻找增广路,时间复杂度大概为O(|E||V|2)。
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int INF=0x3f3f3f3f; 4 const int maxn=1005; 5 struct edge{int to,cap,rev;};//指向节点to,边容量是cap,rev是记录为当前邻接点to反向边的编号 6 vector<edge> G[maxn];//邻接表,G[i][j]表示节点i连接的第j条边包含的所有信息 7 int t,n,m,x,y,c,level[maxn];//level数组在bfs时为分层图所用 8 void add_edge(int from,int to,int cap){//向图中增加一条从s到t容量为cap的边 9 G[from].push_back((edge){to,cap,G[to].size()}); 10 G[to].push_back((edge){from,0,G[from].size()-1}); 11 } 12 //通过bfs给图分层次 13 void bfs(int s){ 14 memset(level,-1,sizeof(level));//刚开始每个节点的层次置为-1 15 queue<int> que;//队列实现bfs 16 level[s]=0;//源点s为第0层 17 que.push(s); 18 while(!que.empty()){//给图分层 19 int v=que.front();que.pop(); 20 for(size_t i=0;i<G[v].size();++i){//遍历节点v与之相连的每条边 21 edge &e=G[v][i];//取出与节点v相连的第i条边 22 if(e.cap>0&&level[e.to]<0){//如果边残余流量大于0,且节点e.to还未分层 23 level[e.to]=level[v]+1;//节点e.to的层次为指向它的节点v所在层次数加1 24 que.push(e.to); 25 } 26 } 27 } 28 } 29 //通过dfs寻找最短增广路 30 int dfs(int v,int t,int f){//v->t,当前流量是f 31 if(v==t)return f;//如果当前节点v为本身,则直接返回当前的流量值 32 for(size_t i=0;i<G[v].size();++i){//遍历节点v与之相连的每条边 33 edge &e=G[v][i];//取出与节点v相连的第i条边 34 if(e.cap>0 && level[v]<level[e.to]){//如果该边残流量大于0,且邻接点e.to是v的下一级,就增广下去 35 int d=dfs(e.to,t,min(f,e.cap));//维护增广路径上的最小容量:s-->t,最小容量为d 36 if(d>0){//回溯时如果增广路径上的最小容量大于0,说明找到了增广路径,将增广路径上的每条边减去最小可流量 37 e.cap-=d;//正向边减去最小流量 38 G[e.to][e.rev].cap+=d;//反向边加上最小流量 39 return d;//回溯到上一层,返回当前增广路径上的最小容量;当回到源点S时,继续查找是否还有增广路径 40 } 41 } 42 } 43 return 0;//否则说明没有增广路,返回当前的最小的流量为0 44 } 45 //Dinic算法实现最大流,每个阶段执行完一次bfs分层之后,只需查找当前层次图中是否还增广路径即可 46 int max_flow(int s,int t){ 47 int flow=0; 48 while(1){ 49 bfs(s);//每个阶段先bfs将图分层标记 50 if(level[t]<0)return flow;//如果分层之后,终点t的层次小于0,即没有被分层,说明已没有增广路了,直接返回当前最大流量 51 int f=dfs(s,t,INF); 52 while(f>0){//在该层次图中找到增广路的最小流量 53 flow+=f;//先将其流量相加 54 f=dfs(s,t,INF);//然后循环找该层次图中是否还有增广路径 55 } 56 } 57 } 58 int main(){ 59 while(~scanf("%d",&t)){ 60 for(int cas=1;cas<=t;++cas){ 61 scanf("%d%d",&n,&m); 62 for(int i=0;i<=n;++i)G[i].clear(); 63 while(m--){ 64 scanf("%d%d%d",&x,&y,&c); 65 add_edge(x,y,c); 66 } 67 printf("Case %d: %d ",cas,max_flow(1,n)); 68 } 69 } 70 return 0; 71 }
以上是关于题解报告:hdu 3549 Flow Problem(最大流入门)的主要内容,如果未能解决你的问题,请参考以下文章