大家成为朋友的最早时刻
给定一组N个人,每个人都有一个从0到(N – 1)的唯一 ID 值和一个由M个{U, V, time}形式的元素组成的数组arr[] ,表示这个人U将结识这个人V在给定的时间。如果U是V的朋友,或者U是熟悉V的人的朋友,则假设人U与人V相识。任务是找出每个人相互认识的最早时间。
例子:
Input: N = 4, arr[] = {{0, 1, 2}, {1, 2, 3}, {2, 3, 4}}
Output: 4
Explanation: Initially, the number of people are 4, i.e, {0}, {1}, {2}, {3}.
- At time = 2, {0} and {1} became friends. Therefore, the group of acquainted people becomes {0, 1}, {2}, {3}.
- At time = 3, {1} and {2} became friends. Therefore, the group of acquainted people becomes {0, 1, 2}, {3}.
- At time = 4, {2} and {3} became friends. Therefore, the group of acquainted people becomes {0, 1, 2, 3}.
Hence, at time = 4, every person became acquainted with each other.
Input: N = 6, 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}}
Output: 24
方法:给定的问题可以使用不相交集联合数据结构来解决。这个想法是按照时间值递增的顺序执行人与人之间的联合操作。所需的答案将是所有人属于同一集合的时间。请按照以下步骤解决给定的问题:
- 根据此处讨论的算法,使用union和findSet函数实现 Disjoint Set Union Data Structure。
- 初始化一个变量time ,它存储了 DSU 当前时间戳的值。
- 按时间递增的顺序对给定的数组arr[]进行排序。
- 使用变量i遍历给定的数组arr[] ,并在(U i , V i )之间执行联合运算并将当前时间戳更新为时间i 如果U i和V 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)