网络流中求最大流的模板

const int N = 205;
const int inf = 0x3f3f3f3f;
int visit[N], layer[N];
int n, m;// 1代表源点,m代表汇点
int g[N][N];
bool layering() //进行分层
{
    deque<int> q;//双向队列
    memset(layer, -1, sizeof(layer));
    q.push_back(1);
    layer[1] = 0;
    while (!q.empty())
    {
        int front = q.front();
        q.pop_front();
        for (int i = 1; i <= m; i++)
        {
            if (layer[i] == -1 && g[front][i] > 0)
            {
                layer[i] = layer[front] + 1;
                if (i == m) return true;
                else    q.push_back(i);
            }
        }
    }
    return false;
}
int dinic()
{
    int maxflow = 0;
    deque<int> q;
    while (layering()) 
    {
        memset(visit, 0, sizeof(visit));
        q.push_back(1), visit[1] = 1;
        while (!q.empty())
        {
            int front = q.back();
            if (front == m) //如果该点是汇点
            {
                int minflow = inf, minflow_no;// 最小流以及最小流的起始点
                for (int i = 1; i < (int)q.size(); i++) //在双向队列里寻找
                {
                    int s = q[i - 1], e = q[i];
                    if (g[s][e] < minflow) minflow = g[s][e], minflow_no = s;
                }
                maxflow += minflow;
                for (int i = 1; i < (int)q.size(); i++) //添加反向边
                {
                    int s = q[i - 1], e = q[i];
                    g[s][e] -= minflow, g[e][s] += minflow;
                }
                while (!q.empty()&&q.back()!=minflow_no) //回溯到最小流的起始点或栈顶
                {
                    visit[q.back()] = 0;
                    q.pop_back();
                }
            }
            else  //如果不是汇点则继续向下寻找
            {
                int i;
                for ( i = 1; i <= m; i++)
                {
                    if (g[front][i] > 0 && layer[i] == layer[front] + 1 && !visit[i])
                    {
                        visit[i] = 1;
                        q.push_back(i);
                        break;
                    }
                }
                    if (i > m) //如果没找到则回溯
                    {
                        q.pop_back();
                    }

            }
        }
    }
    return maxflow;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值