• hdu1532最大流EK与SAP算法


    EK是最朴素的最大流算法了,但效率比较慢,当然代码也比较清晰,思路去看LRJ的白书就行了。

    但是由于网上大牛总结SAP基本上是解决最大流的最标准模板了,

     网上大牛说基本没有什么最大流能卡SAP。

    EK代码:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    const int N = 210;   //小规模   不用考虑效率
    #define INF  1<<20
    int f[N][N];int r[N][N];int c[N][N];
    int a[N];int q[N];int p[N];
    int main()
    {
        int sum,s,n,m,b,t,x,v,k;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            memset(c,0,sizeof(c));
            memset(f,0,sizeof(f));
            for(int i=0;i<n;i++)
            {
                scanf("%d%d%d",&x,&b,&t);
                c[x][b]+=t;            //注意该题有重边
            }
            sum=0;
    
            while(1)
            {
                s=1; int top=0;int last=0;
                memset(p,0,sizeof(p));
                memset(a,0,sizeof(a));
                memset(q,0,sizeof(q));
                a[s]=INF;
                q[top++]=s;
                while(top>last)
                {
                    int u=q[last++];
                    for(int v=1;v<=m;v++)
                    {
                        if(!a[v]&&c[u][v]>f[u][v])
                        {
                            p[v]=u;q[top++]=v;             //记录v的父亲,加入队列
                            a[v]=a[u]<c[u][v]-f[u][v]?a[u]:c[u][v]-f[u][v];        //最小残量
                        }
                    }
                }
                if(!a[m])  break;    //若没有更新  说明已经不存在增广路
                    for(k=m;k!=s;k=p[k])
                    {
                        f[p[k]][k]+=a[m];
                        f[k][p[k]]+=a[m];
                    }
                    sum+=a[m];
            }
            printf("%d\n",sum);
        }
        return 0;
    }
    

    SAP模板:

    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    const int maxn = 220;
    const int inf = 10000000;//不要开太大
    int c[maxn][maxn];
    int q[maxn], pre[maxn];
    int level[maxn], gap[maxn];
    int n, m;
    int s, t;
    void init_sap(){
        memset(level,  1, sizeof (level));
        //printf("---    %d\n", level[2]);
        //for(int i = 0; i <= n; i ++) level[i] =  n + 310;
        memset(gap, 0, sizeof gap);
        memset(pre, -1, sizeof pre);
        int qs = 0, qe = 0;
        q[qe++] = t;
        level[t] = 0;
        gap[ level[t] ] ++;
        while(qs < qe){
            int hd = q[qs++];
            for(int i = 1; i <= n; i ++){
                if(level[i] > n && c[i][hd] > 0){//level[i] >= n  也可以,why ?
                    q[qe++] = i;
                    level[i] = level[hd] + 1;
                    gap[ level[i] ] ++;
                }
            }
        }
    }
    int find_path(int u){
        for(int i = 1; i <= n; i ++)
          if(c[u][i] > 0 && level[u] == level[i] + 1) return i;
        return -1;
    }
    int relabel(int u){
        int tmp = inf;
        for(int i = 1; i <= n; i ++)
          if(c[u][i] > 0 && tmp > level[i] + 1)
            tmp = level[i] + 1;
        if(tmp == inf) tmp = n;
        return tmp;
    }
    int sap(){
        init_sap();
        int flow = 0, u = s;
        while(level[s] <= n){
            int v = find_path(u);
            if(v > 0){
                pre[v] = u;
                u = v;
                if(u == t){
                    int min_flow = inf;
                    for(int i = t; i != s; i = pre[i])
                      if(min_flow > c[ pre[i]][i])
                        min_flow = c[ pre[i]][i];
                    for(int i = t; i != s; i = pre[i]){
                        c[pre[i]][i] -= min_flow;
                        c[i][pre[i]] += min_flow;
                    }
                    flow += min_flow;
                    u = s;
                }
            }else{
                if(-- gap[ level[u]] == 0) return flow;
                int v = relabel(u);
                gap[v] ++;
                level[u] = v;
                if(u != s) u = pre[u];
            }
        }
        return flow;
    }
    int main(){
        while(~scanf("%d%d", &m, &n)){
            memset(c, 0, sizeof c);
            for(int i = 1; i <= m; i ++){
                int u, v, w;
                scanf("%d%d%d", &u, &v, &w);
                c[u][v] += w;
            }
            s = 1, t = n;
            int flow = sap();
            printf("%d\n", flow);
        }
        return 0;
    }



     

  • 相关阅读:
    家庭网络拓扑架构
    网络基础概念(IP、MAC、网关、子网掩码)
    centos7搭建docker并部署lnmp (转)
    docker容器里面安装php的redis扩展
    docker 安装ps命令
    Docker Ubuntu容器安装ping
    docker 安装nginx
    CentOS7 安装特定版本的Docker
    docker 卸载旧版本
    Centos7搭建Docker部署LNMP
  • 原文地址:https://www.cnblogs.com/amourjun/p/5134163.html
Copyright © 2020-2023  润新知