📜  将多对多映射转换为最大一对一映射

📅  最后修改于: 2021-10-26 05:52:39             🧑  作者: Mango

给定一个包含1..N整数的数组 arr1和另一个包含 1..M整数的数组 arr2arr1 的每个元素都映射到arr2 中的多个元素。任务是最大化两个数组之间可能的一对一映射的数量。

这里一对一映射意味着arr1的唯一元素必须映射到arr2 的唯一元素。
映射以 V对向量的形式给出,其中V.first()表示 arr1 的元素, V.second()表示arr2 的元素。

例子:

Input:  N = 3, M = 3
        arr1[] = {1, 2, 3}
        arr2[] = {1, 2, 3}
        V = { {1, 1}, {2, 1}, {2, 2},
              {3, 1}, {3, 2}, {3, 3} }
Output: 3
Explanation: 
If we carefully see here mappings are 
              1 -------->  {1}
              2 -------->  {1, 2}
              3 -------->  {1, 2, 3}
so, maximum number of unique pairings
can be done as
              1 -------->  {1}
              2 -------->  {2}
              3 -------->  {3}

Input: N = 3, M = 1
        V = { {1, 1}, {2, 1}, {3, 1} };
Output: 1
Explanation: 
Either 1 can be mapped or 2 or 3.
so maximum one mapping is possible.

方法:这里使用的方法是贪婪。
预处理步骤
我们得到一个对向量,其中包含以未排序方式的映射信息,例如-

因此,我们将此映射信息转换为集合映射的向量。
例如:

这是以一对多的映射形式表示信息。
这可以通过下图很容易理解

步骤

  1. 找到 arr1[] 中与 arr2[] 元素映射次数最少的元素。
  2. 将此元素映射到其对应集合的第一个元素。
  3. 删除此元素的所有映射。
  4. 还要删除所有包含来自 arr2[] 元素的映射,这些映射已经被映射。
  5. 对 arr1[] 的所有元素重复这四个步骤。

下面是上述方法的实现:

// C++ Program to convert many to many mapping
// to maximum no of one to one mappings
  
#include 
using namespace std;
  
// Returns the maximum number
// of one to one mappings between two arrays
int FindMax(vector >& V, int N, int M)
{
    int ans = 0;
  
    // Stores whether an element
    // from the first array is used in mapping
    bool* is_paired = new bool[N];
  
    // Contains mapping in sorted form
    vector > mapping(N + 1);
  
    // Initialize all the elements
    // of first array unused
    memset(is_paired, sizeof(is_paired), false);
  
    // Insert mappings in sorted form
    for (int i = 0; i < V.size(); i++) {
        mapping[V[i].first].insert(V[i].second);
    }
  
    // While there is always at least one element
    // which can be mapped to a unique element
    while (true) {
        int lowest = -1;
  
        // Finds element to be mapped
        for (int i = 1; i <= N; i++) {
  
            // There is mapping possible
            if (mapping[i].size() > 0) {
                if (lowest == -1)
                    lowest = i;
                else if (mapping[i].size()
                         < mapping[lowest].size())
                    lowest = i;
            }
        }
  
        if (lowest == -1)
            break;
  
        // Element used in the mapping
        is_paired[lowest] = true;
  
        int remove = *mapping[lowest].begin();
  
        // Delete all the mappings of used element
        for (int i = 1; i <= N; i++) {
  
            mapping[i].erase(remove);
            if (i == lowest) {
                mapping[i].clear();
            }
        }
        ans++;
    }
    return ans;
}
  
// Main Function
int main()
{
    int N = 3;
    int M = 3;
    int arr1[] = { 1, 2, 3 };
    int arr2[] = { 1, 2, 3 };
  
    vector >
        V{ { 1, 1 }, { 2, 1 }, { 2, 2 }, { 3, 1 }, { 3, 2 }, { 3, 3 } };
  
    cout << FindMax(V, N, M) << endl;
  
    return 0;
}
输出:
3

时间复杂度: O(N * x)其中 x 是最大没有一对一的映射。

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程。