图表

时间:2016-11-08 07:32:01

标签: algorithm graph matching

我有2D数组,其中每个元素都是ONon Zero,我必须收集所有1个元素。为此,我将雇用一名工人

`0` - dead coconut tree
`Non Zero` - living tree

一名工人开始在活树上收割,并沿着四个主要方向之一(即北,南,东或西)的直线树木继续收割。当满足下列条件之一时,工人停止收获椰子

  • 工人遇到了一棵枯死的椰子树。
  • 工人撞到种植园边缘(即没有更多 那个方向可收获的树木。)。

示例数组看起来像这样:
enter image description here

因此需要最少4名工人 enter image description here

问题:

当我知道这是Maximum Matching Problem时,我很震惊,我不知道它是怎么回事。 以下是使用索引标记水平和垂直条带的代码

m=1;
for (int i=0; i<r; i++) {
        int j = 0;
        while (j < c && a[i][j] < m) j++;

        while (j < c) {
            while (j < c && a[i][j] >= m) {
                h[i][j] = hcnt;
                j++;
            }
            hcnt++;
            while (j < c && a[i][j] < m) j++;
        }
    }
    int vcnt = 0;
    for (int j=0; j<c; j++) {
        int i = 0;
        while (i < r && a[i][j] < m) i++;
        while (i < r) {
            while (i < r && a[i][j] >= m) {
                v[i][j] = vcnt;
                i++;
            }
            vcnt++;
            while (i < r && a[i][j] < m) i++;
        }
    }

所以我的问题是如何添加边缘以及为什么它是最大匹配问题,有人可以解释这背后的直觉,为什么最大匹配可以解决这个问题。
Original Question

以下代码添加边缘。我不知道我们是如何添加边缘的,为什么它正在工作

int s = 0, t = hcnt + vcnt + 1;
    for (int i=0; i<hcnt; i++) addEdge(s, i+1, 1);
    for (int i=0; i<r; i++) {
        for (int j=0; j<c; j++) if(a[i][j] >= m) {
            addEdge(1 + h[i][j], 1 + hcnt + v[i][j], 1);
        }
    }
    for (int i=0; i<vcnt; i++) addEdge(1 + hcnt + i, t, 1);

1 个答案:

答案 0 :(得分:1)

这个想法如下:我们需要采取一些垂直和水平线,以便覆盖所有树木,并最大限度地减少拾取的线条数量。

带树的每个单元格成为图形中的边缘。每条垂直线成为图形左侧部分的顶点,每条水平线成为右侧部分的顶点。现在问题相当于在此图中找到顶点覆盖。最大匹配的大小等于任何二分图中顶点覆盖的大小(它或多或少是众所周知的定理)。