zoukankan      html  css  js  c++  java
  • 网络流(一)----最大流Ford-Fulkerson算法

    感谢YB大神的总结.

    以HDU1532为例的Ford_Fulkerson算法

    #include <cstdio>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <map>
    
    using namespace std;
    
    const int inf = 0x3f;
    const int INF = 0x3f3f3f3f;
    const int maxn = 1005;
    
    struct Node
    {
        int to, flow, next;
    }edge[maxn * maxn];
    
    int n, m; //顶点数,   边数
    int S, T; //源点, 汇点
    int tot; //记录邻接表边数
    int s[maxn];//DFS保存 结点的  栈
    int pre[maxn], rec[maxn], mins[maxn], head[maxn];
    
    void Add_edge(int a, int b, int c)
    {
        edge[tot].to = b; edge[tot].flow = c; edge[tot].next = head[a];
        head[a] = tot++;
        edge[tot].to = a; edge[tot].flow = 0; edge[tot].next = head[b];
        head[b] = tot++;
    }
    
    void Init()
    {
        tot = 0;
        memset(head, -1, sizeof(head));
    }
    
    inline int DFS()
    {
        int top = 1; 
        memset(pre, -1, sizeof(pre));
        s[top] = S;
        pre[S] = S;
        mins[S] = INF;
        while(top)
        {
            int v = s[top--];
            for(int i = head[v]; i != -1; i = edge[i].next)
            {
                int u = edge[i].to;
                if(pre[u] == -1 && edge[i].flow > 0)
                {
                    pre[u] = v;
                    rec[u] = i;
                    mins[u] = min(mins[v], edge[i].flow);
                    s[++top] = u;
                }
            }
            
            if(pre[T] != -1)  //直到找到了汇点
                return mins[T];//每次返回增广路径中容量最小的
        }
        return -1; // 不存在增广路径
    }
    
    int Ford_Fulkerson()
    {
        int add, Maxflow = 0;
    
        while((add = DFS()) != -1)
        {//算法知道无法找到增广路径才停止
            Maxflow += add;
            for(int i = T; i != S; i = pre[i]) //修改残余网络
            {
                edge[rec[i]].flow -= add; //正向减去流量
                edge[rec[i]^1].flow += add;//反向增加流量
            }
        }
        return Maxflow;
    }
    int main()
    {
        while(~scanf("%d %d", &n, &m))
        {
            int i, j, k, s, e, c;
            Init();
            for(int i = 0; i < n; i++)
            {
                cin >> s >> e >> c;
                Add_edge(s, e, c);
            }
            S = 1; T = m;
            cout << Ford_Fulkerson() << endl;
        }
        return 0;
    }
    

      下面是Edmonds-Karp算法代码的实现,bfs使得找到的增广路节点数最少,和上面dfs版本代码的唯一不同就是把保存节点的栈改成了队列:

    #include <cstdio>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <map>
    
    using namespace std;
    
    const int inf = 0x3f;
    const int INF = 0x3f3f3f3f;
    const int maxn = 1005;
    
    struct Node
    {
        int to, flow, next;
    }edge[maxn * maxn];
    
    int n, m; //顶点数,   边数
    int S, T; //源点, 汇点
    int tot; //记录邻接表边数
    int q[maxn];//DFS保存 结点的  栈
    int pre[maxn], rec[maxn], mins[maxn], head[maxn];
    
    void Add_edge(int a, int b, int c)
    {
        edge[tot].to = b; edge[tot].flow = c; edge[tot].next = head[a];
        head[a] = tot++;
        edge[tot].to = a; edge[tot].flow = 0; edge[tot].next = head[b];
        head[b] = tot++;
    }
    
    void Init()
    {
        tot = 0;
        memset(head, -1, sizeof(head));
    }
    
    
    inline int bfs()  //bfs寻找增广路
    {
    	int h,t;
    	h=t=0;
    	memset(pre,-1,sizeof(pre));
    	q[h]=S;
    	pre[S]=S;
    	mins[S]=INF;
    	while(h<=t)
    	{
    		int v=q[h++];
    		for(int i=head[v];i!=-1;i=edge[i].next)
    		{
    			int u=edge[i].to;
    			if(pre[u]==-1 && edge[i].flow>0)
    			{
    				pre[u]=v;
    				rec[u]=i;
    				mins[u]=min(mins[v],edge[i].flow);
    				q[++t]=u;
    			}
    		}	
    		if(pre[T]!=-1) //直到找到了汇点T
    		return mins[T];//每次返回增广路径中,容量最小的值
    	}
    	return -1; // 不存在增广路径
    }
    
    int Edmonds_Karp()   
    {
    	int add,Maxflow=0;
    	while((add=bfs())!=-1) //算法直到无法找到增广路径时才停止
    	{
    		Maxflow+=add;
    		for(int i=T;i!=S;i=pre[i])  //修改残留网络
    		{
    			edge[rec[i]].flow-=add; //正向减去流量
    			edge[rec[i]^1].flow+=add;//反向增加流量
    		}
    	}
    	return Maxflow;
    }
    
    int main()
    {
        while(~scanf("%d %d", &n, &m))
        {
            int i, j, k, s, e, c;
            Init();
            for(int i = 0; i < n; i++)
            {
                cin >> s >> e >> c;
                Add_edge(s, e, c);
            }
            S = 1; T = m;
            cout << Edmonds_Karp() << endl;
        }
        return 0;
    }
    

     

  • 相关阅读:
    期望的线性性
    排列组合问题选胡
    ABAP Control Framework(9): Tree
    ABAP Control Framework(8): Toolbar
    ABAP Control Framework(7): Picture
    ABAP Control Framework(6): Calendar
    ABAP Control Framework(5): 不同Control之间Drag & Drop事件
    ABAP Control Framework(4): ALV List
    ABAP Control Framework(3): Text Editer
    ABAP Control Framework(2): HTML Viewer
  • 原文地址:https://www.cnblogs.com/tenlee/p/4456822.html
Copyright © 2011-2022 走看看