zoukankan      html  css  js  c++  java
  • POJ 1273 第一个SAP(ISAP)

    /* sap学了很长时间,一直不敢下手写,结果就是不写永远不会真正的理解算法的含义,sap理论很多算法书上都有讲解,但我还是建议看数学专业 图论的书,比如 《有向图的理论,算法及应用》,这本书的内容非常棒,相信看过的都知道吧,比其他算法书上讲的透多了。
    SAP有个优化就是 当出现断链时,就可以直接退出,还有个优化是当前弧的优化,这两个优化只需要一句话+一个数组就解决了,相当实惠,好的ISAP执行的效率真的非常高,我写的ISAP用的是链式前向星法表示。
    这个就算是模板了吧,虽然写的不是很好。。*/

    #include<iostream>
    #include<cstdio>
    #include<memory.h>
    #include<cmath>
    using namespace std;
    
    #define MAXN 500
    #define MAXE 40000
    #define INF 0x7fffffff
    
    long ne,nv,tmp,s,t,index;
    
    struct Edge{
        long next,pair;
        long v,cap,flow;
    }edge[MAXE];
    long net[MAXN];
    long ISAP()
    {
        long numb[MAXN],dist[MAXN],curedge[MAXN],pre[MAXN];
        long cur_flow,max_flow,u,tmp,neck,i;
        memset(dist,0,sizeof(dist));
        memset(numb,0,sizeof(numb));
        memset(pre,-1,sizeof(pre));
        for(i = 1 ; i <= nv ; ++i)
            curedge[i] = net[i];
        numb[nv] = nv;
        max_flow = 0;
        u = s;
        while(dist[s] < nv)
        {
            /* first , check if has augmemt flow */
            if(u == t)
            {
                cur_flow = INF;
                for(i = s; i != t;i = edge[curedge[i]].v) 
                {  
                    if(cur_flow > edge[curedge[i]].cap)
                    {
                        neck = i;
                        cur_flow = edge[curedge[i]].cap;
                    }
                }
                for(i = s; i != t; i = edge[curedge[i]].v)
                {
                    tmp = curedge[i];
                    edge[tmp].cap -= cur_flow;
                    edge[tmp].flow += cur_flow;
                    tmp = edge[tmp].pair;
                    edge[tmp].cap += cur_flow;
                    edge[tmp].flow -= cur_flow;
                }
                max_flow += cur_flow;
                u = neck;
            }
            /* if .... else ... */
            for(i = curedge[u]; i != -1; i = edge[i].next)
                if(edge[i].cap > 0 && dist[u] == dist[edge[i].v]+1)
                    break;
            if(i != -1)
            {
                curedge[u] = i;
                pre[edge[i].v] = u;
                u = edge[i].v;
            }else{
                if(0 == --numb[dist[u]]) break;
                curedge[u] = net[u];
                for(tmp = nv,i = net[u]; i != -1; i = edge[i].next)
                    if(edge[i].cap > 0)
                        tmp = tmp<dist[edge[i].v]?tmp:dist[edge[i].v];
                dist[u] = tmp + 1;
                ++numb[dist[u]];
                if(u != s) u = pre[u];
            }
        }
        
        return max_flow;
    }
    int main() {
        long i,j,np,nc,m,n;
        long a,b,val;
        long g[MAXN][MAXN];
        while(scanf("%d%d",&ne,&nv)!=EOF)
        {
            s = 1;
            t = nv;
            memset(g,0,sizeof(g));
            memset(net,-1,sizeof(net));
            for(i=0;i<ne;++i)
            {
                scanf("%ld%ld%ld",&a,&b,&val);
                g[a][b] += val;
             }
             for(i=1;i<=nv;++i)
                 for(j = i; j <= nv;++j)
                     if(g[i][j]||g[j][i])
                     {
                         edge[index].next = net[i];
                         edge[index].v = j;
                         edge[index].cap = g[i][j];
                         edge[index].flow = 0;
                         edge[index].pair = index+1;
                         net[i] = index++;
                         edge[index].next = net[j];
                         edge[index].v = i;
                         edge[index].cap = g[j][i];
                         edge[index].flow = 0;
                         edge[index].pair = index-1;
                         net[j] = index++;
                     }
            printf("%ld\n",ISAP());
        }
        return 0;
    }
    
  • 相关阅读:
    leetcode——36.有效的数独
    leetcode——60.第K个排列
    leetcode——128. 最长连续序列
    leetcode——81. 搜索旋转排序数组 II
    leetcode——49.字母异构词分组
    leetcode——75.颜色分类
    leetcode——44.通配符匹配
    leetcode——88.合并两个有序数组
    leetcode——116.填充每一个节点的下一个右侧节点指针
    树莓派系统终端中让文件和文件夹显示不同颜色的设置
  • 原文地址:https://www.cnblogs.com/lvpengms/p/1662738.html
Copyright © 2011-2022 走看看