Process Restricted Friend Requests

hard graph union find

Problem

There are n people numbered 0 to n - 1. You are given a list of restrictions, where each pair [x, y] means person x and person y can never become friends — not even indirectly through other friends. You are also given a list of requests, where each pair [u, v] asks to make u and v friends. Process the requests in order: a request succeeds only if accepting it would not place any restricted pair into the same friend group. Return a boolean array telling whether each request was accepted.

Inputn = 5, restrictions = [[0,1],[1,2],[2,3]], requests = [[0,4],[1,2],[3,1],[3,4]]
Output[true, false, true, false]
Request [0,4] is fine. [1,2] is restricted directly, so reject. [3,1] is allowed. [3,4]: by now 0 and 4 are friends and 1,3 are friends; joining 3 and 4 would link group {3,1} with {4,0}, putting restricted pair (0,1) together — reject.

def friend_requests(n, restrictions, requests):
    parent = list(range(n))
    def find(x):
        while parent[x] != x:
            parent[x] = parent[parent[x]]
            x = parent[x]
        return x
    answer = []
    for u, v in requests:
        ru, rv = find(u), find(v)
        ok = True
        if ru != rv:
            for x, y in restrictions:
                rx, ry = find(x), find(y)
                if {rx, ry} == {ru, rv}:
                    ok = False
                    break
        if ok:
            parent[ru] = rv
        answer.append(ok)
    return answer
function friendRequests(n, restrictions, requests) {
  const parent = Array.from({ length: n }, (_, i) => i);
  function find(x) { while (parent[x] !== x) { parent[x] = parent[parent[x]]; x = parent[x]; } return x; }
  const answer = [];
  for (const [u, v] of requests) {
    const ru = find(u), rv = find(v);
    let ok = true;
    if (ru !== rv) {
      for (const [x, y] of restrictions) {
        const rx = find(x), ry = find(y);
        if ((rx === ru && ry === rv) || (rx === rv && ry === ru)) { ok = false; break; }
      }
    }
    if (ok) parent[ru] = rv;
    answer.push(ok);
  }
  return answer;
}
class Solution {
    int[] parent;
    int find(int x) { while (parent[x] != x) { parent[x] = parent[parent[x]]; x = parent[x]; } return x; }
    public boolean[] friendRequests(int n, int[][] restrictions, int[][] requests) {
        parent = new int[n];
        for (int i = 0; i < n; i++) parent[i] = i;
        boolean[] answer = new boolean[requests.length];
        for (int i = 0; i < requests.length; i++) {
            int ru = find(requests[i][0]), rv = find(requests[i][1]);
            boolean ok = true;
            if (ru != rv) {
                for (int[] r : restrictions) {
                    int rx = find(r[0]), ry = find(r[1]);
                    if ((rx == ru && ry == rv) || (rx == rv && ry == ru)) { ok = false; break; }
                }
            }
            if (ok) parent[ru] = rv;
            answer[i] = ok;
        }
        return answer;
    }
}
vector<int> parent;
int find(int x) { while (parent[x] != x) { parent[x] = parent[parent[x]]; x = parent[x]; } return x; }
vector<bool> friendRequests(int n, vector<vector<int>>& restrictions, vector<vector<int>>& requests) {
    parent.resize(n);
    for (int i = 0; i < n; i++) parent[i] = i;
    vector<bool> answer;
    for (auto& req : requests) {
        int ru = find(req[0]), rv = find(req[1]);
        bool ok = true;
        if (ru != rv) {
            for (auto& r : restrictions) {
                int rx = find(r[0]), ry = find(r[1]);
                if ((rx == ru && ry == rv) || (rx == rv && ry == ru)) { ok = false; break; }
            }
        }
        if (ok) parent[ru] = rv;
        answer.push_back(ok);
    }
    return answer;
}
Time: O(q · r · α(n)) Space: O(n)