LeetCode //C - 685. Redundant Connection II

685. Redundant Connection II

In this problem, a rooted tree is a directed graph such that, there is exactly one node (the root) for which all other nodes are descendants of this node, plus every node has exactly one parent, except for the root node which has no parents.

The given input is a directed graph that started as a rooted tree with n nodes (with distinct values from 1 to n), with one additional directed edge added. The added edge has two different vertices chosen from 1 to n, and was not an edge that already existed.

The resulting graph is given as a 2D-array of edges. Each element of edges is a pair [ u i , v i ] [u_i, v_i] [ui,vi] that represents a directed edge connecting nodes u i u_i ui and v i v_i vi, where u i u_i ui is a parent of child v i v_i vi.

Return an edge that can be removed so that the resulting graph is a rooted tree of n nodes. If there are multiple answers, return the answer that occurs last in the given 2D-array.
 

Example 1:

Input: edges = [[1,2],[1,3],[2,3]]
Output: [2,3]

Example 2:

Input: edges = [[1,2],[2,3],[3,4],[4,1],[1,5]]
Output: [4,1]

Constraints:
  • n == edges.length
  • 3 <= n <= 1000
  • edges[i].length == 2
  • 1 < = u i , v i < = n 1 <= u_i, v_i <= n 1<=ui,vi<=n
  • u i ! = v i u_i != v_i ui!=vi

From: LeetCode
Link: 685. Redundant Connection II


Solution:

Ideas:

1. Detect if any node has two parents.

2. If found, store both edges.

3. Use Union-Find to detect cycles.

4. Based on what we find:

  • If a node has two parents and removing the second edge avoids the cycle → remove the second edge.
  • If a node has two parents and removing either still forms a cycle → remove the first edge.
  • If no node has two parents but there’s a cycle → remove the edge causing the cycle.
Code:
int find(int* parent, int x) {
    if (parent[x] != x)
        parent[x] = find(parent, parent[x]);
    return parent[x];
}

bool unionSet(int* parent, int* rank, int u, int v) {
    int pu = find(parent, u);
    int pv = find(parent, v);
    if (pu == pv) return false; // cycle
    if (rank[pu] > rank[pv]) parent[pv] = pu;
    else if (rank[pu] < rank[pv]) parent[pu] = pv;
    else {
        parent[pu] = pv;
        rank[pv]++;
    }
    return true;
}

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* findRedundantDirectedConnection(int** edges, int edgesSize, int* edgesColSize, int* returnSize) {
    int* parent = (int*)malloc((edgesSize + 1) * sizeof(int));
    int* rank = (int*)calloc(edgesSize + 1, sizeof(int));
    int* candidate1 = NULL;
    int* candidate2 = NULL;
    int* parents = (int*)calloc(edgesSize + 1, sizeof(int));

    for (int i = 1; i <= edgesSize; ++i)
        parents[i] = i;

    // Step 1: Check for a node with two parents
    for (int i = 0; i < edgesSize; ++i) {
        int u = edges[i][0], v = edges[i][1];
        if (parents[v] != v) {
            candidate1 = (int*)malloc(2 * sizeof(int));
            candidate2 = (int*)malloc(2 * sizeof(int));
            candidate1[0] = parents[v];
            candidate1[1] = v;
            candidate2[0] = u;
            candidate2[1] = v;
            edges[i][0] = -1; // Mark this edge to skip in union-find
        } else {
            parents[v] = u;
        }
    }

    // Step 2: Union-Find to detect cycle
    for (int i = 1; i <= edgesSize; ++i)
        parent[i] = i;

    for (int i = 0; i < edgesSize; ++i) {
        int u = edges[i][0], v = edges[i][1];
        if (u == -1) continue; // skip the second parent edge
        if (!unionSet(parent, rank, u, v)) {
            free(parent); free(rank); free(parents);
            *returnSize = 2;
            if (candidate1)
                return candidate1;
            int* result = (int*)malloc(2 * sizeof(int));
            result[0] = u; result[1] = v;
            return result;
        }
    }

    // If no cycle was detected, the second edge is the redundant one
    free(parent); free(rank); free(parents);
    *returnSize = 2;
    return candidate2;
}

你可能感兴趣的:(LeetCode,leetcode,c语言,算法)