网络流之最大流(关于poj1273)

//poj1273,网络流之最大流主要概念:
//1,源点,即整个图遍历的起点,POJ1273中是1,注意它只流出,不流入
//2.汇点,即终点POJ1273中为读入的下标,注意它只流入不流出。
//3.容量,即从一点到另一点的最大流量,上限值
//4.最大流问题就是知道源点,汇点,每一条边的容量,求从源点到汇点的最大流量
//5.残余网络:针对每条边的流量,就是每一条边还剩余的流量,正常是可以用另一个数组表示用了多少,这里为了节省空间,就将增加的流量减去,比如原先通过100,增加了10,那么还可以增加90
//6.增广路:简单来说就是一条通路,只不过每一条边(注意是这条路径上的!)的流量都比原来的残余网络(原来路径上的)要大。
//这里有几个问题值得关注:
//1,最大流的大小在哪取,简单来说就是从源点流出的总量,或流入汇点的总量,当然这里程序是记录下每一次增加的流量,因为初始状态没有流量,所以每增加一次,必然就多一些流量(因为增广路肯定经过源点的嘛)
//2. 何时取到最大流的图,即不存在增广路,因为如果存在增广路必然还可以增加流量。
//3.注意理解反向边,大致就是假设A路,B路都经过S边,如果我A路走S这条路就将另一种可能堵死了,所以A路要有反向边,B路可以通过反向边行进(因为经过一次反向边相当于把流量又还回去)
//这部分听起来很复杂,但是实现起来很容易,只需记录下该节点前一个是什么,然后找到增广路后倒退,(非常像并查集有木有~~)从前一个节点到后一个节点的通路可用流量减少,反向回路流量增加~~
//流程就是先用邻接矩阵存储,然后每一次找增广路,找的过程中事情较多,要记录下该节点的前一个,返回可增加的流量,寻找可增加流量的过程需要理解,可比作数组寻找最小值,即默认之前一个数组里保存的是可增加的最小值
//然后看后面路径是否小于最小值,如果后面可增长的路径已经小于最小值,那么可增长的最小值要更新,
//若增长路不存在,那么说明已经是最大流的图了,返回最大流,否则开始从尾向头更改路径剩余流量。
#include 
#include 
#include 
#include 
using namespace std;
int a[201][201];
int end;//终点
int path[201];
int bfs(int s,int e)
{
    int i,u,temp;
    int flow[201];
    int vis[201];
    memset(vis,0,sizeof(vis));
    memset(flow,0,sizeof(flow));
    queueq;
    flow[s]=99999;//让起点的流量为最大值,因为接下来是比较从起点到周围的距离,必然是要记录从起点到该点的距离,所以flow[s]要最大
    vis[s]=1;//标记起点已经被访问
    q.push(s);
    while(!q.empty())
    {
     temp=q.front();
     q.pop();
     for (i=1;i<=end;i++)
        if ((!vis[i]&&a[temp][i]>0))//如果没有被访问过,同时存在回路
     {
         flow[i]=a[temp][i]


你可能感兴趣的:(图)