使用福特弗里克森将N名员工安排到担任角色的M职位

时间:2014-08-08 08:10:31

标签: php algorithm ford-fulkerson

我正在尝试使用Ford-Fulkerson解决数学问题,但我遇到了一些问题。

这是问题

    I have a list of employees (Jack, John, Al, ...).
    I have a list of roles (R1, R2, R3, ...).
    I have a list of working positions (W1, W2, W3, ...).

    Every employee has a set of roles, like Jack has R1 and R2, ...
    Every working position has a set of roles that can support,
    like to work in position W1 you need R1 or R2, ...

我需要找到最佳的员工配置 - 工作岗位,以确保每个工作岗位都有一名具有合适职责的员工(每个岗位一名员工)。

我尝试使用此算法http://www.geeksforgeeks.org/maximum-bipartite-matching/

我建立了一个矩阵,每个员工都有一行,每个工作岗位都有一列。如果X员工可以在Y位置工作,我放入X行,Y列值为1,否则我放0。

上面用PHP重写的算法很有效,直到员工人数<=位置数。

如果我的员工多于职位,算法计算时间往往会分散到无限。

以下是算法代码:

function maxMatch($matrix, $cols) {
    $match = array();
    foreach ($cols as $v => $item) {
        $match[$item] = -1;
    }
    $result = 0;
    foreach ($matrix as $u => $row) {
        $seen = array();
        foreach ($cols as $v => $item) {
            $seen[$item] = 0;
        }
        if ($this->checkVertex($matrix, $u, $seen, $match)) {
            print_r($match);
            $result++;
        }
    }
    return $match;
}

function checkVertex($matrix, $u, $seen, &$match) {
    foreach ($matrix[$u] as $v => $row) {
        if ($matrix[$u][$v] && !$seen[$v]) {
            $seen[$v] = TRUE;
            if ($match[$v] < 0 || $this->checkVertex($matrix, $match[$v], $seen, $match)) {
                $match[$v] = $u;
                return TRUE;
            }
        }
    }
    return FALSE;
}

一切都像上面链接中的算法,除了我传递$ cols数组,包含列的索引(因为它们是位置ID而不是数字排序)。

这是我创建矩阵的方式:

function createMatrix($year, $month, $day, $shift) {
    global $sql;

    $result = $sql->query("VERY HUGE SELECT FOR EMPLOYEES AND POSITIONS MATCH");

    while ($row = $result->fetch_assoc()) {
        $matrix[$row['employee']][$row['position']] = 1;
    }
    return $matrix;
}

因此我只在员工和职位匹配的地方放置1。

任何人都有任何关于如何解决问题的线索?提前致谢

1 个答案:

答案 0 :(得分:0)

您按值传递seen。这是不正确的。它应该通过引用传递。你现在拥有的实际上是某种回溯(原始算法时间复杂度证明是基于这样一个事实,即在深度优先搜索期间每个顶点最多可以被访问一次,而在当前的实现中并非如此)。这就是它运作缓慢的原因。通过引用传递seen应该解决它。