网络流/最大流算法与题目总结

最大流模型为有N个湖(点),他们有小溪相连(边),每个小溪都有它们单位时间的最大流量,最大流求的是一个湖(源点)到另一个湖(汇点)单位时间内能流入的最大流量。

求最大流的一个算法为 ford_fulkerson算法,算法思想:

1.从源点开始寻找一条路径到汇点,记录这条路径流量最小的边的流量为m,然后最大流量+=m,然后每条边的流量都减去m,然后反向更新流量(每条边反方向的流量加上m);

2.重复步骤1直到找不到路径到汇点为止,最终的最大流量即为所求的最大流。

ford_fulkerson C++模板:

[cpp]  view plain copy
  1. void ford_fulkerson(int s,int e)  
  2. {  
  3.     queue<int>Q;  
  4.     int u,v;  
  5.     while(1)                            
  6.     {  
  7.         Maxflow=0;//最大流初始化  
  8.         memset(maxflow,0,sizeof(maxflow));//每次寻找增广路径都将每个点的流入容量置为0  
  9.         memset(visit,0,sizeof(visit));//标记一个点是否已经压入队列  
  10.         maxflow[s]=INT_MAX;//源点的容量置为正无穷  
  11.         Q.push(s);   // 将源点压入队列  
  12.         while(!Q.empty())   //当队列不为空  
  13.         {  
  14.             u=Q.front();  
  15.             Q.pop();  
  16.             for(v=1;v<=N;v++)     
  17.             {  
  18.                 if(!visit[v]&&flow[u][v]>0)   
  19.                 {  
  20.                     visit[v]=1;  
  21.                     father[v]=u;//记录下他的父亲方便往后的正反向更新  
  22.                     Q.push(v);  
  23.                     maxflow[v]=(maxflow[u]<flow[u][v]?maxflow[u]:flow[u][v]);//当前点的容量为父亲点容量与边流量的较小者  
  24.                 }  
  25.             }  
  26.             if(maxflow[e]>0) //如果找到了汇点并且汇点容量不为0则清空队列。  
  27.             {  
  28.                 while(!Q.empty())  
  29.                     Q.pop();  
  30.                 break;  
  31.             }  
  32.         }  
  33.         if(maxflow[e]==0)//已经找不到到汇点的增光路经了,就退出整个循环  
  34.             break;  
  35.         for(i=e;i!=s;i=father[i])  
  36.         {  
  37.             flow[father[i]][i]-=maxflow[e];//正向更新  
  38.             flow[i][father[i]]+=maxflow[e];//反向更新  
  39.         }  
  40.         Maxflow+=maxflow[e];//更新最大流  
  41.     }  
  42. }  

一个证明需要反向更新的例子:

网络流/最大流算法与题目总结_第1张图片

 

这个图从1到6明显最的流量为3+3=6,但如果不用反向更新,由于用BFS首先找到一条路径1-2-3-6,然后1-2,2-3,3-6这几条边被更新成了0,就再也找不到增广路径到6了,而1-5-3的剩余的5个流量就无路可走了,用反向更新会再在3-2这里加一条流量为3的边,这时候1-5-3的5流量就可以通过这条边到2再到4再到6了,这就是反向更新的需要。

最大流题目:

POJ1273

最大流入门题,代码:

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<queue>  
  3. using namespace std;  
  4. const int MAXN = 205;  
  5. const int maxint = 0x3f3f3f3f;  
  6. int flow[MAXN][MAXN],maxflow[MAXN],father[MAXN];  
  7. int i,Maxflow,M,visit[MAXN];  
  8. void ford_fulkerson()  
  9. {  
  10.     queue<int>Q;  
  11.     int u,v;  
  12.     while(1)  
  13.     {  
  14.         memset(maxflow,0,sizeof(maxflow));  
  15.         memset(visit,0,sizeof(visit));  
  16.         maxflow[1]=INT_MAX;  
  17.         Q.push(1);  
  18.         while(!Q.empty())  
  19.         {  
  20.             u=Q.front();  
  21.             Q.pop();  
  22.             for(v=1;v<=M;v++)  
  23.             {  
  24.                 if(!visit[v]&&flow[u][v]>0)  
  25.                 {  
  26.                     visit[v]=1;  
  27.                     father[v]=u;  
  28.                     Q.push(v);  
  29.                     maxflow[v]=(maxflow[u]<flow[u][v]?maxflow[u]:flow[u][v]);  
  30.                 }  
  31.             }  
  32.             if(maxflow[M]>0)  
  33.             {  
  34.                 while(!Q.empty())  
  35.                     Q.pop();  
  36.                 break;  
  37.             }  
  38.         }  
  39.         if(maxflow[M]==0)  
  40.             break;  
  41.         for(i=M;i!=1;i=father[i])  
  42.         {  
  43.             flow[father[i]][i]-=maxflow[M];  
  44.             flow[i][father[i]]+=maxflow[M];  
  45.         }  
  46.         Maxflow+=maxflow[M];  
  47.     }  
  48. }  
  49. int main()  
  50. {  
  51.     int N,si,ei,ci;  
  52.     while(cin>>N>>M&&N!=EOF)  
  53.     {  
  54.         Maxflow=0;  
  55.         memset(flow,0,sizeof(flow));  
  56.         for(i=0;i<N;i++)  
  57.         {  
  58.             cin>>si>>ei>>ci;  
  59.             flow[si][ei]+=ci;  
  60.         }  
  61.         ford_fulkerson();  
  62.         cout<<Maxflow<<endl;  
  63.     }  
  64.     return 0;  
  65. }  

POJ 1459

这题关键是建图,为该图自建一个源点和汇点就行了。。

POJ 1149

 灰常经典,无敌建图题,最大流必做题。

1.增加源点0与汇点t;

2.如果某顾客有某个猪圈的钥匙,如果之前有顾客有这个猪圈的钥匙,那么加一条之前那顾客到当前这个顾客的边,权值为无限大(方便剩下的猪能传递给当前的顾客),否则就在源点0与这个顾客加一条边,权值为这个猪圈的猪数目。还需要加一条该顾客到汇点t的边,权值为该顾客的需要猪的数量。

3.求源点0到汇点t的最大流

 

你可能感兴趣的:(网络流/最大流算法与题目总结)