• 网络流--最大流


    网络流的所有算法都是基于一种增广路的思想,下面首先简要的说一下增广路思想,其基本步骤如下:

    1.找到一条从源点到汇点的路径,使得路径上任意一条边的残量>0(注意是大于而不是大于等于,这意味着这条边还可以分配流量),这条路径便称为增广路
    2.找到这条路径上最小的F[u][v](我们设F[u][v]表示u->v这条边上的残量即剩余流量),下面记为flow

    3.将这条路径上的每一条有向边u->v的残量减去flow,同时对于起反向边v->u的残量加上flow
    4.重复上述过程,直到找不出增广路,此时我们就找到了最大流

      最大流板子题,洛谷草地排水。先用bfs求出每个点深度,再用一个类似dfs的东西找到能新走到汇点的权值。多走几次就行了。

           这有一个很棒的博客,大家可以看一看

      https://www.cnblogs.com/SYCstudio/p/7260613.html

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    struct node
    {
        int x,y,c,next,other;
    };
    node a[2110000];
    int len = 0,last[5000],st,ed;
    int list[5000]; 
    queue <int> qu;
    void add(int x,int y,int w)
    {
        int k1,k2;
        a[++len].next = last[x];
        k1 = len;
        a[len].x = x;
        a[len].y = y;
        a[len].c = w;
        last[x] = len;
        a[++len].next = last[y];
        k2 = len;
        a[len].x = y;
        a[len].y = x;
        a[len].c = 0;
        last[y] = len;
        a[k1].other = k2;
        a[k2].other = k1;
    }
    int h[5000];
    bool bfs()
    {
        memset(h,0,sizeof(h));
        h[st] = 1;
        int head,tail;
        list[1] = st;
        head = 1;
        tail = 2;
        while(head != tail)
        {
            int x = list[head];
    //        cout<<x<<endl;
            for(int k = last[x];k;k = a[k].next)
            {
                int y = a[k].y;
    //            cout<<k<<" "<<a[k].c<<" "<<y<<endl;
                if(a[k].c > 0 && h[y] == 0)
                {
                    h[y] = h[x] + 1;
                    list[tail++] = y;
    //                cout<<y<<endl;
                }
            }
            head++;
        }
        /*for(int i = 1;i <= ed;i++)
        cout<<h[i]<<" ";
        cout<<endl;
        for(int i = 1;i <= len;i++)
        cout<<a[i].c<<" "; 
        cout<<endl;*/
        if(h[ed] > 0)
        return true;
        else
        return false;
    }
    int mymin(int x,int y){return x < y ? x : y;}
    int find(int x,int f)
    {
        if(x == ed)
        return f;
        int s = 0,t;
        for(int k = last[x];k;k = a[k].next)
        {
            int y = a[k].y;
            if(s < f && h[y] == (h[x] + 1) && a[k].c > 0)
            {
    //            cout<<a[k].c<<" "<<f - s<<endl;
                t = find(y,mymin(a[k].c,f - s));
                s += t;
    //            cout<<t<<endl;
                a[k].c -= t;
                a[a[k].other].c += t;
    //            cout<<k<<"_"<<a[k].c<<" "<<a[k].other<<"_"<<a[a[k].other].c<<endl;
            }
        }
        if(s == 0)
        h[x] = 0;
        return s;
    }
    int main()
    {
        int n,m;
        cin>>m>>n;
        st = 1;
        ed = n;
        len = 0;
        memset(last,0,sizeof(last)); 
        for(int i = 1;i <= m;i++)
        {
            int x,y,z;
            cin>>x>>y>>z;
            add(x,y,z);
        }
    //    cout<<endl;
        int s = 0,t;int l = 0;
        while(bfs() == true)
        {
            s += find(st,99999999);
        }
        cout<<s;
        return 0;
    }
    /*
    4 4
    1 2 10
    2 4 5
    2 3 20
    3 4 10
    */
  • 相关阅读:
    java基础
    JAVASE 安装步骤
    MySQL 45道练习题
    MySQL 多表查询
    2018-08-07JDBC连接MySQL+增删改表格+SQL注入问题及其预处理对象PreparedStatement解决方案
    2018-08-06Java中的异常捕获和Throw详细细节
    2018-08-03List接口方法+LinkedList方法+Vector集合+Set接口下HashSet和LinkedHashSet集合+HashCode()+equals()方法对于Set接口判断重复的详细细节
    2018-08-01集合Collection+Iterator迭代器+泛型+增强For循环
    2018-07-31包装类与基本数据类型String的转换+System类详细知识+Arrays类+大数据(BigInteger+BigDecimal)运算
    2018-07-27Final+Static+匿名对象+3中代码块
  • 原文地址:https://www.cnblogs.com/DukeLv/p/9112734.html
Copyright © 2020-2023  润新知