当前位置:编程学习 > C/C++ >>

网络流改进SAP算法模版、HDU 1532 Drainage Ditches(解题报告)

本次网络流算法看了两天了,先学习了EK算法,发现速度不够快,于是查找资料,得网络流诸多算法中主流算法(SAP算法)学习之。
相关链接:
1、网络流的算法分类:http://www.notonlysuccess.com/index.php/algorithm-of-network/
2、牛人博客,几种算法的分析:http://blog.csdn.net/abcjennifer/article/details/5556455
3、较详细的SAP算法分析:http://hi.baidu.com/hewei156/blog/item/f17038326b2f91c0a2cc2b78.html

研究的一天多的代码模版(该模版正确性及可用性有待证明,以后若出现什么问题将进行修改):
[cpp] 
#include<iostream> 
#include<algorithm> 
#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 
#include<queue> 
#include<math.h> 
#define maxn 205 
#define INF 100000000 
using namespace std; 
 
int n,m,s,t;// n点数,m边数,s起点,t终点 
int map[maxn][maxn],fa[maxn],gap[maxn],level[maxn];//map有向图,fa父节点, 
//gap[i]=j表示以汇点距离为i的点有j个,level[i]=j表示点i与汇点距离为j  
 
void sap_bfs()//反向 BFS 初始化所有顶点的距离标号、初始化level和gap数组  

    memset(level,1,sizeof(level));//这个很神奇,每个int的4字节都变成0000 0001 
//即数组被初始化为二进制的00000001 00000001 00000001 00000001 ,十进制为16843009  
    memset(gap,0,sizeof(gap)); 
    queue<int> q; 
    q.push(t); 
    level[t]=0;//汇点距离为0  
    gap[level[t]]++; 
    while(!q.empty()) 
    { 
        int temp=q.front(); q.pop(); 
        for(int i=1;i<=n;i++)   
        if(level[i]>n && map[i][temp]>0) 
        { 
            q.push(i); 
            level[i]=level[temp]+1; 
            gap[level[i]]++; 
        } 
    } 

 
int fine_path(int u)//查找残量网络中是否有与u相连 且距离为1的点  

    for(int i=1;i<=n;i++) if(map[u][i]>0 && level[u]==level[i]+1) 
        return i; 
    return -1; 

 
int Advance()//找到汇点时进行增广  

    int i,minflow=INF; 
    for(i=t;i!=s;i=fa[i]) if(minflow>map[fa[i]][i])//查找这条增广路中最小的流量  
    { 
        minflow=map[fa[i]][i]; 
    } 
    for(i=t;i!=s;i=fa[i]) 
    { 
        map[fa[i]][i]-=minflow; 
        map[i][fa[i]]+=minflow;//反向边也要操作  
    } 
    return minflow; 

 
int retreat(int u)//对点u重新设置最小的距离  

    int fine=INF; 
    for(int i=1;i<=n;i++) if(map[u][i]>0 && fine>level[i]+1) 
        fine=level[i]+1; 
    if(fine==INF) fine=n;//找不到的话设置为最大,即点u不会再被经过  
    return fine; 

 
int cxbsap() 

    sap_bfs(); 
    int i,j,v,u=s,flow=0;//初始化  
    while(level[s]<=n)//源点与汇点距离小于n时执行,要是不存在源点到汇点的通路直接跳出  
    { 
        v=fine_path(u);// 找u的下一个点  
        if(v>0) 
        { 
            fa[v]=u;//找到后标记父节点  
            u=v;//把v赋值给u,如果不是汇点,直接跳回75行了  
            if(u==t) 
            { 
                flow+=Advance(); 
                u=s;//找的一条路径后重新查找  
            } 
        } 
        else 
        { 
            if(--gap[level[u]]==0) return flow;//如果其中一个距离个数为0,即出现断层,没有通路看,直接跳出  
            v=retreat(u); 
            gap[v]++; 
            level[u]=v; 
            if(u!=s) u=fa[u]; 
        } 
    } 
    return flow; 

 
int main() 

//  freopen("in.txt","r",stdin); 
    int i,j,a,b,x; 
    while(~scanf("%d%d",&m,&n)) 
    { 
        memset(map,0,sizeof(map)); 
        for(i=0;i<m;i++) 
        { 
            scanf("%d%d%d",&a,&b,&x); 
            map[a][b]+=x; 
        } 
        s=1; t=n; 
        int ans=cxbsap(); 
        printf("%d\n",ans); 
    } 
    return 0; 

 

我发现其实自己有点易做图症,我喜欢带参数的函数,所以:
[cpp] 
/*
网络流改进sap模版:HDU1532
计算一个点编号1~n的网络的最大流;
时间复杂度o(v*e^2)  v点数,e边数
陈小宾,2012、8、13凌晨 
*/ 
#include<iostream> 
#include<algorithm> 
#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 
#include<queue> 
#include<math.h> 
#define maxn 205 
#define INF 100000000 
using namespace std; 
 
int n,m;// n点数,m边数,s起点,t终点 
int map

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,