• 网络流初步: 最大流


    好吧。

    直接上模板。。。

    思想能够看看这里点击打开链接


    </pre><pre name="code" class="cpp">
    queue<int> q;  
    memset(flow,0,sizeof(flow));  
    int f = 0;  
    while(true){  
        memset(a,0,sizeof(a));  
        a[s] = INF;  
        q.push(s);  
        while(!q.empty)){    //BFS找增广路  
            int u = q.front(), q.pop();  
            for(int v = 1; v <= n; v++){  
                if(!a[v] && cap[u][v] > flow[u][v]){   //找到新结点  
                    a[v] = (a[u]<cap[u][v]-flow[u][v] ? a[u] : cap[u][v]-flow[u][v]); //s-v路径上最小残留量  
                    q.push(v);  
                    p[v] = u;       //记录v的父亲。并增加FIFO队列中  
                }  
            }  
        }  
        if(a[t]==0) break;   //找不到,则当前流已经是最大流  
        for(int v = t; v!=s; v=p[v]){     // 从汇点往回走  
            flow[p[v]][v] += a[t];   // 更新正向流量  
            flow[v][p[v]] -= a[t];    //更新反向流量  
        }  
        f += a[t];                        //更新从s流出的总流量  
    }  
    

    Edmond Karp算法详细实现(C/C++)
    #include <iostream>
    #include <queue>
    #include <algorithm>
    
    using namespace std;
    1
    const int msize = 205;
     
    int N, M;   // N--路径数, M--结点数
    int r[msize][msize];  //
    int pre[msize];  // 记录结点i的前向结点为pre[i]
    bool vis[msize]; // 记录结点i是否已訪问
     
    // 用BFS来推断从结点s到t的路径上是否还有delta
    
    // 即推断s,t之间是否还有增广路径,若有。返回1
    
    bool BFS(int s, int t)
    {
        queue<int> que;
        memset(pre, -1, sizeof(pre));
        memset(vis, false, sizeof(vis));
     
        pre[s] = s;
        vis[s] = true;
        que.push(s);
     
        int p;
        while(!que.empty())
        {
            p = que.front();
            que.pop();
            for(int i=1; i<=M; ++i)
            {
                if(r[p][i]>0 && !vis[i])
                {
                    pre[i] = p;
                    vis[i] = true;
                    if(i == t)  // 存在增广路径
                        return true;
                    que.push(i);
               }
            }
        }
        return false;
    }
     
    int EK(int s, int t)
    {
        int maxflow = 0, d;
        while(BFS(s, t))
        {
            d= INT_MAX;
            // 若有增广路径,则找出最小的delta
            for(int i=t; i!=s; i=pre[i])
                d = min(d, r[pre[i]][i]);
            // 这里是反向边,看解说
            for(int i=t; i!=s; i=pre[i])
            {
                r[pre[i]][i] -= d;
                r[i][pre[i]] += d;
            }
            maxflow += d;
        }
        return maxflow;
    }
     
    int main()
    {
        while(cin >> N >> M)
        {
            memset(r, 0, sizeof(r));
            int s, e, c;
            for(int i=0; i<N; ++i)
            {
                cin >> s >> e >> c;
                r[s][e] += c;   // 有重边时则加上c
            }
     
            cout << EK(1, M) << endl;
        }
        return 0;
    }

    </pre><pre>

    另一种是紫书上的。。这个要难些。

    <pre name="code" class="cpp">
    struct Edge
    {
        int from, to, cap, flow;
        Edge (int u, int v, int c, int f):from(u), to(v), cap(c), flow(f) {}
    };
    
    struct EdmondsKarp
    {
        int n, m;
        vector<Edge> edges;
        vector<int> G[MAXN];
        int a[MAXN];
        int p[MAXN];
    
        void init(int n)
        {
            for(int i=0; i<n; i++)
                G[i].clear();
            edges.clear();
        }
    
        void AddEdge(int from, int to, int cap)
        {
            edges.push_back( Edge(from, to, cap, 0) );
            edges.push_back( Edge(to, from, 0, 0) );
            m = edges.size();
            G[from].push_back(m-2);
            G[to].push_back(m-1);
        }
    
        int Maxflow(int s, int t)
        {
            int flow = 0;
            for( ; ; )
            {
                memset(a, 0, sizeof(a));
                queue<int> Q;
                Q.push(s);
                a[s]=INF;
                while( !Q.empty() )
                {
                    int x = Q.front();
                    Q.pop();
                    for(int i=0; i<G[x].size(); i++)
                    {
                        Edge& e = edges[ G[x][i] ];
                        if( !a[e.to] && e.cap > e.flow )
                        {
                            p[e.to] = G[x][i];
                            a[e.to] = min(a[x], e.cap-e.flow);
                            Q.push(e.to);
                        }
                    }
                    if( a[t] ) break;
                }
                if( ! a[t] )  break;
                for(int u=t; u!=s; u=edges[ p[u] ].from )
                {
                    edges[ p[u] ].flow += a[t];
                    edges[ p[u]^1 ].flow -= a[t];
                }
                flow += a[t];
            }
            return flow;
        }
    
    };

    
    
    
    
    还是先弄弄easy的吧。。

    。那个真的。。Orz。。

    第一次尝试能够做HDU1532。。。



  • 相关阅读:
    本地http://localhost打不开怎么办
    C#中lock死锁实例教程
    结对-四则运算答题器-项目进度
    Forward团队-爬虫豆瓣top250项目-代码设计规范
    Forward团队-爬虫豆瓣top250项目-设计文档
    学习使用github
    Forward团队-爬虫豆瓣top250项目-团队编程项目开发环境搭建过程
    课后作业-阅读任务-阅读提问-1
    20170915-构建之法:现代软件工程-阅读笔记
    结对-四则运算答题器-设计文档
  • 原文地址:https://www.cnblogs.com/gccbuaa/p/6900529.html
Copyright © 2020-2023  润新知