网络流——最大流问题 EK算法

网络流——最大流问题 EK算法

谁便一个图

题:就像水从 s 流到 t ,给你每条边能流过的大小,问你 s —>t 最大能流多少?这就是最大流问题。

增广路算法

增广路算法,就是随便找 s->t的一条路,然后改变流过边的流量,再找另一条路直到找不到路

算法过程如下图(图片来自http://blog.csdn.net/yiqingnian28/article/details/23388633 博客)

alt

看着这个图片很可能不知道为什么要加一条反向边 ?这是为了避免这种情况
alt
当走1 -> 2 ->3 ->4 这条路时会把1-> 3->4堵上这样求出的就成 1了,很明显这是错的,于是加了一条反向边(相当于减去一条正向流量)3 -> 2 ;这样就成了1 -> 2 ->3 ->4 1-> 3 ->2 ->4


#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define maxn 2009  //边的两倍
#define maxnn 20  //点
struct node
{
    int v,next,c,f;
    //  c 容量 f流量
};
int head[maxn];
int o;
node edg[maxn];
inline void add(int u,int v,int val)  //邻接表
{
    edg[o].v=v;
    edg[o].next=head[u];
    edg[o].f=0;
    edg[o].c=val;
    head[u]=o++;

}
void intt()
{

    memset(head,-1,sizeof(head));
    o=0;
}
int max_flow(int s,int t)
{

    int flow=0;    //流
    int a[maxnn];  //记录流过点的值
    int p[maxnn];   //记录父节点 用于回溯
    while(1)
    {
        memset(a,0,sizeof(a));
        queue<int>q;
        while(!q.empty()) q.pop();
        q.push(s);
        a[s]=inf;      //起始点为无限大
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=head[u]; ~i; i=edg[i].next)
            {
                if(!a[edg[i].v]&&edg[i].c>edg[i].f)          //必须容量大于流量才能流
                {
                    p[edg[i].v]=i;
                    a[edg[i].v]=min(a[u],edg[i].c-edg[i].f);  //能经过该点的一条路的流量
                    q.push(edg[i].v);


                }
            }
            if(a[t]) break;  //如果流到了汇点 结束

        }
        if(!a[t]) return flow;  //如果没有能扩冲的 结束
        for(int i=t; i!=s; i=edg[p[i]^1].v)  //更改流过的点的流量
        {
            edg[p[i]].f+=a[t];
            edg[p[i]^1].f-=a[t];
        }
        flow+=a[t];  //流入汇点的
    }






    return flow;
}
int main()
{
    int tt;
    cin>>tt;
    int js=1;
    while(tt--)
    {
        intt();
        int n,m;
        cin>>n>>m;
        for(int i=0; i<m; i++)
        {
            int u,v,val;
            cin>>u>>v>>val;
            add(u,v,val);
            add(v,u,0);

        }

        cout<<"Case "<<js++<<": "<<max_flow(1,n)<<endl;
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37493070/article/details/78235734