HackerRank "Training the army" - Max Flow

First problem to learn Max Flow.

Ford-Fulkerson is a group of algorithms - Dinic is one of it.
It is an iterative process: we use BFS to check augament-ability, and use DFS to augment it.

Here is the code with my comments from its tutorial

#include <cmath>
#include <climits>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;

/*
*     Graph Model
*/
const int MAXA = 400005;
const int MAXV = 1005;

int A, V, source, dest;
// index based logging
int cap[MAXA], flow[MAXA], ady[MAXA], nexts[MAXA], last[MAXV]; 
int now[MAXA], level[MAXV];

void ADD(int u, int v, int c) // from u to v with cap c
{
    //    + edge
    cap[A] = c; flow[A] = 0;
    ady[A] = v; nexts[A] = last[u]; last[u] = A++;
    //    - edge
    cap[A] = 0; flow[A] = 0;
    ady[A] = u; nexts[A] = last[v]; last[v] = A++;
}

/*
*     Dinic Algorithm
*/
bool BFS(int source, int dest)
{
    memset(level, -1, sizeof(level));
    level[source] = 0;

    queue<int> q;
    q.push(source);
    while (!q.empty() && level[dest] == -1)
    {
        int u = q.front(); q.pop(); // from
        for (int i = last[u]; i != -1; i = nexts[i])
        {
            int v = ady[i]; // to
            if (level[v] == -1 && flow[i] < cap[i])
            {
                level[v] = level[u] + 1; // mark level
                q.push(v);
            }
        }

    }
    return level[dest] != -1;
}

int DFS(int u, int aux)
{
    if (u == dest) return aux;

    for (int i = now[u]; i != -1; now[u] = i = nexts[i])
    {
        int v = ady[i];
        // next aux-able level node
        if (level[v] > level[u] && flow[i] < cap[i])
        {
            int ret = DFS(v, min(aux, cap[i] - flow[i]));
            if (ret > 0)
            {
                flow[i] += ret; // + edge
                flow[i ^ 1] -= ret;// - edge
                return ret;
            }
        }
    }
    return 0;
}

long long Dinic()
{
    long long flow = 0, aum;
    while (BFS(source, dest))
    {
        for (int i = 0; i <= V; i++) now[i] = last[i];
        while ((aum = DFS(source, INT_MAX)) > 0) flow += aum;
    }
    return flow;
}

/*
*
*/
int main()
{
    //    [index]: first n is cluster, next m is wizard..
    memset(last, -1, sizeof(last));

    int n, m, v, cc;
    cin >> n >> m;

    source = 0;
    V = dest = n + m + 1;

    //    1.     Source -> Cluster with No. with people
    //        Cluster -> Dest with cap of 1 - means no transform
    //        no. of people of each skill
    for (int i = 1; i <= n; i++)
    {
        cin >> v;
        if (v) ADD(source, i, v);
        ADD(i, dest, 1); // a non-transformed edge
    }
    //    wizard info
    for (int i = 1; i <= m; i++) // m wizards
    {
        //    array A - index of from-skill
        cin >> cc;
        for (int j = 0; j < cc; j++)
        {
            cin >> v;
            ADD(v, n + i, 1); // skill[v](from) -> wizard[i]
        }
        //    array B - index of to-skill
        cin >> cc;
        for (int j = 0; j < cc; j++)
        {
            cin >> v;
            ADD(n + i, v, 1); // wizard[i] -> skill[v](to)
        }
    }

    cout << Dinic() << endl;
    return 0;
}

 

你可能感兴趣的:(HackerRank "Training the army" - Max Flow)