leetcode 1557. Minimum Number of Vertices to Reach All Nodes

insert image description here
Given a directed acyclic graph (DAG), there are n vertices: 0~n - 1, and
the edge [from, to] is the edge from the vertex from to to.
Find the smallest set of vertices from which all vertices in the graph can be reached (not every point in the set can reach all vertices, but the combination of their respective reached points is all vertices).
Guaranteed to have a solution.

Ideas:

First look at Example1, where the two points 0 and 3 only go out but not come in.
All points other than 0 and 3 cannot reach these two points, so points other than 0 and 3 cannot be selected.

The same is true for Example2, the 3 points 0, 2, and 3 can only go out but not in, and
you cannot reach these 3 points by selecting points other than them.

Does that mean that if you choose only exits but no entry, you will be able to reach all points?
The title says that there is a guaranteed solution, as long as all the points that can only exit but not enter can be found.

In addition, a DAG should have no isolated points, so all points are connected,
as long as you find all the points that can only go out but not in, you will be able to reach all other points.

Here, the from in [from, to] is regarded as the parent of to.

Did you think of union-find, but here you can't find the root like in union-find,
because it's a directed graph, and the child can't go back to the parent.
For example, 0->1->2, root=0 cannot be found through 2, because it is a directed edge, 2 cannot reverse to 0, and the
parent of 2 can only be recorded as 1.

In this way, you can write.

    public List<Integer> findSmallestSetOfVertices(int n, List<List<Integer>> edges) {
    
    
        int[] parent = new int[n];
        List<Integer> res = new ArrayList<>();

        for(int i = 0; i < n; i++) {
    
    
            parent[i] = i;
        }

        for(List<Integer> edge: edges) {
    
    
            int n1 = edge.get(0);
            int n2 = edge.get(1);
            parent[n2] = n1;
        }

        for(int i = 0; i < n; i++) {
    
    
            if(parent[i] == i) res.add(i);
        }
        return res;
    }

But writing like this is not efficient enough.
In fact, parent[n2]=doesn’t matter. As long as you know that n2 has a parent, you can prove that n2 is not a point that only exits but not enters.
It can be marked with a boolean.
The last one that is not marked is the point that can only exit but not enter.

    public List<Integer> findSmallestSetOfVertices(int n, List<List<Integer>> edges) {
    
    
        boolean[] parent = new boolean[n];
        List<Integer> res = new LinkedList<>();

        for(List<Integer> edge: edges) {
    
    
            parent[edge.get(1)] = true;
        }

        for(int i = 0; i < n; i++) {
    
    
            if(!parent[i]) res.add(i);
        }
        return res;
    }

insert image description here

Guess you like

Origin blog.csdn.net/level_code/article/details/130742397
Recommended