leetcode 1557. Número mínimo de vértices para atingir todos os nós

insira a descrição da imagem aqui
Dado um grafo acíclico direcionado (DAG), existem n vértices: 0~n - 1, e
a aresta [de, para] é a aresta do vértice de para para.
Encontre o menor conjunto de vértices a partir do qual todos os vértices do grafo podem ser alcançados (não necessariamente todos os pontos do conjunto podem alcançar todos os vértices, mas a combinação de seus respectivos pontos alcançados é todos os vértices).
Garantia de solução.

Ideias:

Primeiro, observe o Exemplo 1, onde os dois pontos 0 e 3 apenas saem, mas não entram.
Todos os pontos, exceto 0 e 3, não podem alcançar esses dois pontos, portanto, pontos diferentes de 0 e 3 não podem ser selecionados.

O mesmo vale para o Exemplo 2, os 3 pontos 0, 2 e 3 só podem sair, mas não entrar, e
você não pode alcançar esses 3 pontos selecionando outros pontos além deles.

Isso significa que se você escolher apenas saídas, mas nenhuma entrada, conseguirá atingir todos os pontos?
O título diz que existe uma solução garantida, basta descobrir todos os pontos que só podem sair, mas não entrar.

Além disso, um DAG não deve ter pontos isolados, então todos os pontos estão conectados,
desde que sejam encontrados todos os pontos que só podem sair, mas não entrar, todos os outros pontos podem ser alcançados.

Aqui, o from in [from, to] é considerado o pai de to.

Você pensou em union-find, mas aqui você não pode encontrar a raiz como em union-find,
porque é um gráfico direcionado e o filho não pode voltar para o pai.
Por exemplo, 0->1->2, root=0 não pode ser encontrado por meio de 2, porque é uma aresta direcionada, 2 não pode ser revertido para 0 e o
pai de 2 só pode ser registrado como 1.

Desta forma, você pode escrever.

    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;
    }

Mas escrever assim não é eficiente o suficiente.
Na verdade, parent[n2]=Não importa quem, desde que você saiba que n2 tem um pai, você pode provar que n2 não é um ponto que só sai, mas não entra , e
pode ser marcado com um booleano.
O último que não está marcado é o ponto que só pode sair mas não entrar.

    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;
    }

insira a descrição da imagem aqui

Acho que você gosta

Origin blog.csdn.net/level_code/article/details/130742397
Recomendado
Clasificación