📜  大家成为朋友的最早时刻

📅  最后修改于: 2022-05-13 01:56:05.353000             🧑  作者: Mango

大家成为朋友的最早时刻

给定一组N个人,每个人都有一个从0(N – 1)的唯一 ID 值和一个由M{U, V, time}形式的元素组成的数组arr[] ,表示这个人U将结识这个人V在给定的时间。如果UV的朋友,或者U是熟悉V的人的朋友,则假设人U与人V相识。任务是找出每个人相互认识的最早时间。

例子:

方法:给定的问题可以使用不相交集联合数据结构来解决。这个想法是按照时间值递增的顺序执行人与人之间的联合操作。所需的答案将是所有人属于同一集合的时间。请按照以下步骤解决给定的问题:

  • 根据此处讨论的算法,使用unionfindSet函数实现 Disjoint Set Union Data Structure。
  • 初始化一个变量time ,它存储了 DSU 当前时间戳的值。
  • 按时间递增的顺序对给定的数组arr[]进行排序。
  • 使用变量i遍历给定的数组arr[] ,并在(U i , V i )之间执行联合运算并将当前时间戳更新为时间i 如果U iV i属于不同的集合。
  • 如果完全遍历数组arr[]后的集合总数为1 ,则返回变量time的值,否则返回-1

下面是上述方法的实现:

C++
// C++ program for the above approach
#include "bits/stdc++.h"
using namespace std;
 
// Implementation of DSU
class UnionFind {
 
    vector parent, rank;
 
    // Stores the current timestamp
    int time;
 
    // Stores the count of current sets
    int count;
 
public:
    // Constructor to create and
    // initialize sets of N items
    UnionFind(int N)
        : parent(N), rank(N), count(N)
    {
        time = 0;
 
        // Creates N single item sets
        for (int i = 0; i < N; i++) {
            parent[i] = i;
            rank[i] = 1;
        }
    }
 
    // Function to find the set of
    // given item node
    int find(int node)
    {
        if (node == parent[node])
            return node;
        return parent[node]
               = find(parent[node]);
    }
 
    // Function to perform the union of
    // two sets represented by u and v,
    // and update the value of time
    void performUnion(int u, int v,
                      int updatedTime)
    {
 
        if (count == 1)
            return;
 
        // Find current sets of u and v
        int rootX = find(u);
        int rootY = find(v);
 
        if (rootX != rootY) {
 
            // Put smaller ranked item under
            // bigger ranked item if ranks
            // are different
            if (rank[rootX] < rank[rootY]) {
                parent[rootX] = rootY;
            }
            else if (rank[rootX] > rank[rootY]) {
                parent[rootY] = rootX;
            }
            else {
                parent[rootX] = rootY;
                rank[rootY] += 1;
            }
 
            // Update the value of the
            // current timestamp
            time = updatedTime;
 
            // Update the value of
            // set count
            count--;
        }
    }
 
    // Function to return current
    // set count
    int getCount() { return count; }
 
    // Function to return current
    // time stamp
    int getTime() { return time; }
};
 
// Comparator function to sort the array
// in increasing order of 3rd element
bool cmp(vector& A, vector& B)
{
    return A[2] <= B[2];
}
 
// Function to find the earliest time when
// everyone became friends to each other
int earliestTime(vector >& arr,
                 int N)
{
    // Sort array arr[] in increasing order
    sort(arr.begin(), arr.end(), cmp);
 
    // Initialize a DSU with N elements
    UnionFind unionFind(N);
 
    // Iterate over array arr[] perform
    // union operation for each element
    for (auto& it : arr) {
 
        // Perfoem union operation on
        // it[0] and it[1] and update
        // timestamp to it[2]
        unionFind.performUnion(
            it[0], it[1], it[2]);
    }
 
    // Return Answer
    if (unionFind.getCount() == 1) {
        return unionFind.getTime();
    }
    else {
        return -1;
    }
}
 
// Driver Code
int main()
{
    int N = 6;
    vector > arr
        = { { 0, 1, 4 }, { 3, 4, 5 },
            { 2, 3, 14 }, { 1, 5, 24 },
            { 2, 4, 12 }, { 0, 3, 42 },
            { 1, 2, 41 }, { 4, 5, 11 } };
 
    cout << earliestTime(arr, N);
 
    return 0;
}


输出:
24

时间复杂度: O(N)
辅助空间: O(N)