网络流初步——增广路代码的分析

struct Edge
{
    int from,to,flow,cap;
    Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
};
struct EdmonsKarp()
{
    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) //邻接表形式保存图 ,感谢耀神昨天的讲解,这个Edge明白了是邻接表的变形
{
    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())
        {                     //整个while循环用来找一条增广路当中的最小残余量 
            int x=front();
                Q.pop();
            for(int i=0;i<G[x].size();i++)
            { 
                Edge& e=G[x][i];
                if(!a[e.to]&&e.cap>e.flow)//每调用一条边,比较这条边的残量和其父节点的残量大小 
                {                         //把最小残量保存到当前结点中 
                a[e.to]=min(a[x],e.cap-e.flow); 
                p[e.to]=G[x][i];          //p数组记录到当前结点的前一条边的编号 
                Q.push(e.to);
                }
            }
            if(a[t])  //如果到达汇点了结束寻找 
            break; 
        if(!a[t]) //a数组肯定是一个全局变量,由于每调用一次这个函数只能求出一条增广路增加的量 
        break;    //每次都把a[i]标记,所以当源结点的所有子节点都被标记后,自然到达不了汇点 
        for(int u=t;u!=s;u=edges[p[u].from]) //而每一次函数调用后汇点都要被更新为0,所以当a[t]==0时候 
        {                                    //就是所有的增广路都被跑完的时候 
           edges[p[u]].flow+=a[t];
           edges[p[u]^1].flow-=a[t];    
         }
         flow+=a[t];
         return flow;
    }
}

猜你喜欢

转载自www.cnblogs.com/rainyskywx/p/9975639.html