问题描述:

G=(V,E)是一个有向图,其中每条边(u,v)有一个非负的容量值c(u,v),而且如果E中包含一条边(u,v),那么图中就不存在它的反向边。在流网络中有两个特殊的结点,源结点s和汇点t,源结点s只会流出不会流进,汇点只会流进不会流出,我们要求的就是从源结点流到汇结点的路径的值之和的最大值

EK算法:

算法描述:

每次从残留网络中找出一条从源结点到汇结点的最短路径,流选为路径中的残存容量,依据流更新残存网络(将每条边的残存容量改为当前容量减去流的大小,并添加对应的反向边,边的容量为流的大小)

重复选最短路径,更新残存网络,直到没有最短路径为止

此时的流累加和即为最大流

 

由于每次要找的是最短路径,所以需要用BFS找路径

伪代码

最大流问题之FF算法与EK算法

例子:

初始图:

最大流问题之FF算法与EK算法

第一次路径1->2->4->6,流大小:12

最大流问题之FF算法与EK算法

更新后图为:

最大流问题之FF算法与EK算法

第二次路径为1->3->5->6,流大小:4

最大流问题之FF算法与EK算法

更新后图为:

最大流问题之FF算法与EK算法

 

第三次路径为1->3->5->4->6,流大小:7

最大流问题之FF算法与EK算法

更新后图为:

最大流问题之FF算法与EK算法

此时,再也找不到最短路径,算法结束,则最大流为:12+4+7=23

 

控制台对应输出为:

最大流问题之FF算法与EK算法

 

关键定理证明:

最大流最小割定理:

下面条件等价

1、f是G的一个最大流

2、残存网络不包括任何增广路径

3、|f|=c(S,T),其中(S,T)是流网络的某个切割

1推2:

假定f是G的一个最大流,但残存网络中仍包含有一条增广路径,那么对流f增加流量后,所得的值是严格大于f的值的,这与f是G的一个最大流矛盾

2推3:

假设流网络G不包含任何增广路径,现在定义S为G中存在一条从s到v的路径的所有v的集合,定义T为V-S,则划分(S,T)是流网络G的一个切割。

对S中的任意一个结点u,T中的任意一个结点v

如果(u,v)属于E,则必有f(u,v)=c(u,v)

如果(v,u)属于E,则必有f(v,u)=0

如果(u,v)和(v,u)都不属于E,则f(u,v)= f(v,u)=0

因此

最大流问题之FF算法与EK算法

所以|f| = f(S,T)= c(S,T),得证

3推1:

对于所有切割(S,T),|f|≤c(S,T)

因此,当|f| = c(S,T)时,f就是一个最大流

 

时间复杂度分析

对于一个流网络,我们要分析EK算法的复杂度,实际就是要分析调用bfs的次数,但是bfs的次数是很难分析的,所以需要做一点转换,将对bfs次数的分析转换为其它和它等价的实体量且稍微简单一点的分析

在实际分析中,我们发现关键边的个数和bfs的次数是等价的,所以要分析bfs次数,不妨就分析关键边的个数

 

关键边定义:

边(u,v)的残存容量为最短路径的残存容量,则称为为关键边

任一增广路径都至少存在一条关键边

 

时间复杂度计算:

边(u,v)成为关键边到下一次成为关键边,从原结点到u的距离至少增加2个单位

②由于从源结点s到结点u的中间结点不可能包括s、u或t,所以一直到u成为不可到达结点前,距离最长为v-2

由①②可得边(u,v)成为关键边的次数最多为(V-2)/2,取V/2

 

由于一共有E条边,所以EK算法中关键边总数为O(VE)

总时间 = BFS时间 * BFS次数

由于每次BFS时间为O(E),需要O(VE)次BFS,所以总时间为O(VE²)

 

 

FF算法:

FF算法和EK算法很相似,唯一不同的地方就是FF算法每次找的不是最短增广路径,它找的路径是随机的

 

FF算法缺陷分析:

由于FF算法每次找的增广路径不是最短路径,所以FF算法存在这样一个缺陷:它会使一条边成为关建边的最大次数从原来的V/2上升到K/2(K为所有边中权值最大的边的权值)

举下面一个例子

最大流问题之FF算法与EK算法

图3、FF算法样例图

按照EK算法,边(u,v)和(v,u)成为关键边的最大次数应该是4/2-1 = 1,所以所需要的bfs次数为1+1 = 2次

最大流问题之FF算法与EK算法

图4、FF算法过程图

 

最大流问题之FF算法与EK算法

图5、FF算法过程图

在FF算法中,它将以图4和图5的方式反复流动500000次

边(u,v)和(v,u)成为关键边的最大次数是1000000/2=500000,所以所需要的bfs次数为500000+500000=1000000次,由于调用bfs的效率过低,所以会导致FF算法比EK算法慢

#include <iostream>
#include <queue>
#include <stdlib.h>
#include <time.h>
#include <ctime>
#include <stack>
#define Max 10000000
using namespace std;
class Map{
public:
    int **C;
    int **F;
    int **p;
//    int **F;
    int Node_num;
    int total=0;
    int bfs_count = 0;
public:
    Map(){};
    ~Map(){};
    void set_map();
    void EK();
    int bfs();
    int *pre;
    int *flow;
    queue<int> q;
    void FF();
    int DFS(int start);
    void ba();
    void EK1();
};
void Map::ba()
{
    bfs_count = 0;
    for(int i=0;i<Node_num;i++)
    {
        for(int j=0;j<Node_num;j++)
        {
            C[i][j]=p[i][j];
            F[i][j]=p[i][j];
        }
    }
}
int Map::DFS(int start)
{
    int p=start;
    for(int i=1;i<Node_num;i++)
    {
        if(F[p][i]>0 && pre[i]==-1)
        {
            pre[i]=p;
            flow[i]=min(flow[p],F[p][i]);
            int t=DFS(i);
            if(t != 0)
                return t;
            if(i==Node_num-1)
                return flow[i];
        }
    }
    return 0;
}
void Map::FF()
{
    total=0;
    int temp_flow;
    while(1)
    {
        for(int i=0;i<Node_num;i++)
            pre[i]=-1;
        pre[0]=0;
        flow[0]=Max;
        temp_flow = DFS(0);
//        cout<<"temp_flow:"<<temp_flow<<endl;
        if(temp_flow == 0)
            break;
        else
        {
            int p = Node_num-1;
            while(p!=0)
            {
                F[pre[p]][p] -= temp_flow;
                F[p][pre[p]] += temp_flow;
                p = pre[p];
            }
            total += temp_flow;
        }
    }
    cout<<"FF:"<<total<<endl;
}
void Map::set_map()
{
    int a,b;
    int t1,t2;
    cin >> Node_num;
//    cin >> t2;
    flow = new int[Node_num];
    pre = new int[Node_num];
    C = new int*[Node_num];
    F = new int*[Node_num];
    p = new int*[Node_num];
    for(int i=0;i<Node_num;i++)
    {
        C[i]=new int[Node_num];
        F[i]=new int[Node_num];
        p[i]=new int[Node_num];
    }
    for(int i=0;i<Node_num;i++)
    {
        for(int j=0;j<Node_num;j++)
        {
            C[i][j]=0;
            F[i][j]=0;
            p[i][j]=0;
        }
    }
    for(int i=1;i<Node_num;i++)
    {
        for(int j=0;j<Node_num-1;j++)
        {
            C[j][i]=rand()%100;
            p[j][i]=C[j][i];
        }
    }
//    while(t2--)
//    {
//        a=rand()%Node_num;
//        b=rand()%Node_num;
//        if(a==b ||a==Node_num-1 || b==0)
//        {
//            t2++;
//            continue;
//        }
//        t1=rand()%Node_num;
////        cin>>a>>b>>t1;
//        C[a-1][b-1]+=t1;
//        F[a-1][b-1]+=t1;
//        p[a-1][b-1]+=t1;
//    }
}
void Map::EK1()
{
    total=0;
    for(int i=0;i<Node_num;i++)
    {
        for(int j=i+1;j<Node_num;j++)
        {
            if(C[i][j]>C[j][i])
            {
                C[i][j]-=C[j][i];
                C[j][i]=0;
            }
            else
            {
                C[j][i]-=C[i][j];
                C[i][j]=0;
            }
        }
    }
    int temp_flow;
    while(1)
    {
        temp_flow = bfs();
//        cout<<"temp_flow:"<<temp_flow<<endl;
        if(temp_flow == -1)
            break;
        else
        {
            int p = Node_num-1;
//            cout<<"temp_flow:"<<temp_flow<<endl;
//            int t=p;
//            stack<int> s;
//            while(t!=0)
//            {
//                s.push(t+1);
//                t=pre[t];
//            }
//            cout<<1<<' ';
//            while(!s.empty())
//            {
//                cout<<s.top()<<' ';
//                s.pop();
//            }
//            cout<<endl;

            while(p!=0)
            {
                C[pre[p]][p] -= temp_flow;
                C[p][pre[p]] += temp_flow;
                p = pre[p];
            }
            total += temp_flow;
        }
    }
    cout<<"EK1:"<<total<<endl;
}
void Map::EK()
{
    total=0;
    int temp_flow;
    while(1)
    {
        temp_flow = bfs();
//        cout<<"temp_flow:"<<temp_flow<<endl;
        if(temp_flow == -1)
            break;
        else
        {
            bfs_count++;
            int p = Node_num-1;
            cout<<"temp_flow:"<<temp_flow<<endl;
            int t=p;
            stack<int> s;
            while(t!=0)
            {
                s.push(t+1);
                t=pre[t];
            }
            cout<<1<<' ';
            while(!s.empty())
            {
                cout<<s.top()<<' ';
                s.pop();
            }
            cout<<endl;

            while(p!=0)
            {
                C[pre[p]][p] -= temp_flow;
                C[p][pre[p]] += temp_flow;
                p = pre[p];
            }
            total += temp_flow;
        }
    }
//    cout<<"EK:"<<total<<endl;
}
int Map::bfs()
{
    while(!q.empty())
        q.pop();
    for(int i=0;i<Node_num;i++)
        pre[i]=-1;
    pre[0]=0;
    q.push(0);
    flow[0]=Max;
    while(!q.empty())
    {
        int p = q.front();
        q.pop();
        if(p == Node_num-1)
            break;
        for(int i=1;i<Node_num;i++)
        {
            if(C[p][i]>0 && pre[i]==-1)
            {
                pre[i]=p;
                flow[i]=min(flow[p],C[p][i]);
                q.push(i);
            }
        }
    }
    if(pre[Node_num-1] == -1)
        return -1;
    else
        return flow[Node_num-1];
}
int main()
{
//    {
//        double p;
//        cin>>p;
//        for(int i=1;i<10;i++)
//            cout<<p*i*i*i<<endl;
//    }
    int t=100;
    double t1,t2,t3=0;
    for(int i=1;i<=t;i++)
    {
        int temp=1;
        Map test;
        test.set_map();
//        t1 = clock();
//        for(int j=0;j<temp;j++)
//        {
////            Map test;
////            test.set_map();
//            test.ba();
//            test.EK1();
//        }
//        t2 = clock();
//        cout<<"t1:"<<(t2-t1)/temp<<endl;
        t1 = clock();
        for(int j=0;j<temp;j++)
        {
//            Map test;
//            test.set_map();
            test.ba();
            t1 = clock();
            test.EK();
            t2 = clock();
            t3 += t2-t1;
        }
        cout<<"bfs次数:"<<test.bfs_count<<endl;
        cout<<"时间:"<<t3 / temp<<endl;
        t3=0;
    }
    return 0;
}

 

相关文章:

  • 2021-08-17
  • 2021-05-30
  • 2021-12-25
  • 2022-12-23
  • 2022-12-23
  • 2021-12-07
  • 2021-07-28
猜你喜欢
  • 2022-12-23
  • 2021-09-26
  • 2022-12-23
  • 2021-07-30
  • 2021-12-12
  • 2022-12-23
相关资源
相似解决方案