最大流

56 阅读1分钟

首先是bfs,这是对整个图进行分层,默认后一层等于前一层加1

然后就是dfs,每次搜索,因为之前对图已经分层,所以直接可以按层进行深搜,直到找到n为止

最后就是Dinic了,每次增广找到最短的一条边,并且把所有的正向边减少a反向边增加a

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
const int inf=1e9;

int n,m;
int e[110][110];
int dis[110];
int bfs(int s);
int Find(int x,int minn);
int Dinic();

int main()
{
    int i,u,v,w;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(e,0,sizeof(e));

        for(i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            e[u][v]=w;
        }
        printf("%d\n",Dinic());
    }
    return 0;
}

int bfs(int s)
{
    int A,i;
    memset(dis,-1,sizeof(dis));
    queue<int>q;
    q.push(s);
    dis[1]=0;

    while(!q.empty())
    {
        A=q.front();
        q.pop();
        for(i=1;i<=n;i++)
        {
            if(dis[i]==-1&&e[A][i]>0)
            {
                dis[i]=dis[A]+1;
                q.push(i);
            }
        }
    }
    if(dis[n]>0)
        return 1;
    return 0;
}

int dfs(int x,int minn)
{
    int i,a=0;
    if(x==n)
        return minn;
    for(i=1;i<=n;i++)
    {
        if(e[x][i]>0&&dis[i]==dis[x]+1&&(a=dfs(i,min(minn,e[x][i]))))
        {
            e[x][i]-=a;
            e[i][x]+=a;
            return a;
        }
    }
    return 0;
}

int Dinic()
{
    int temp,sum=0;
    while(bfs(1))
    {
        while(temp=dfs(1,inf))
        {

            sum+=temp;
        }
    }
    return sum;
}