web-dev-qa-db-fra.com

Obtenir une forêt en dehors de l'arbre avec un nombre pair de nœuds

Je suis coincé dans un défi de code et je veux un indice .

PROBLÈME: Une structure de données arborescente (sans cycles) vous est demandée. Il vous est demandé de supprimer autant que possible les "arêtes" (connexions), créant ainsi des arbres plus petits avec un nombre pair de nœuds. Ce problème peut toujours être résolu car il existe un nombre pair de nœuds et de connexions.

Votre tâche consiste à compter les bords supprimés.

Entrée: La première ligne d'entrée contient deux entiers N et M. N est le nombre de sommets et M est le nombre d'arêtes. 2 <= N <= 100. Les M lignes suivantes contiennent deux entiers ui et vi qui spécifient un bord de l’arbre. (Index basé sur 1)

Résultat: Imprimez le nombre d'arêtes supprimées.

Exemple de saisie 

10 9
2 1
3 1
4 3
5 2
6 1
7 2
8 6
9 8
10 8

Exemple de sortie: 2

Explication: En supprimant les arêtes (1, 3) et (1, 6), nous pouvons obtenir le résultat souhaité.

32
g4ur4v

J'ai utilisé BFS pour parcourir les nœuds . Tout d'abord, maintenez un tableau séparément pour stocker le nombre total de nœuds enfants + 1 . Ainsi, vous pouvez attribuer initialement tous les nœuds feuilles de valeur 1 dans ce tableauMaintenant, commencez par le dernier nœud et comptez le nombre d'enfants pour chaque nœud. Cela fonctionnera de bas en haut et le tableau qui stocke le nombre de nœuds enfants facilitera l'optimisation du code au moment de l'exécution.

Une fois que vous obtenez le tableau après avoir obtenu le nombre de nœuds enfants pour tous les nœuds, il vous suffit de compter les nœuds avec un nombre pair de nœuds. Remarque: je n'ai pas inclus le nœud racine dans le décompte à l'étape finale.

23
g4ur4v

Ceci est ma solution. Je n'ai pas utilisé d'arborescence bfs, mais juste un autre tableau pour contenir le nombre total de chaque nœud et de leurs nœuds enfants.

import Java.util.Scanner;
import Java.util.Arrays;

public class Solution {
        public static void main(String[] args) {
                int tree[];
                int count[];

                Scanner scan = new Scanner(System.in);

                int N = scan.nextInt(); //points
                int M = scan.nextInt();

                tree = new int[N];
                count = new int[N];
                Arrays.fill(count, 1);

                for(int i=0;i<M;i++)
                {
                        int u1 = scan.nextInt();
                    int v1 = scan.nextInt();

                    tree[u1-1] = v1;

                    count[v1-1] += count[u1-1];

                    int root = tree[v1-1];

                    while(root!=0)
                    {
                        count[root-1] += count[u1-1];
                        root = tree[root-1];
                    }
                }

                System.out.println("");

                int counter = -1;
                for(int i=0;i<count.length;i++)
                {
                        if(count[i]%2==0)
                        {
                                counter++;
                        }

                }
                System.out.println(counter);

        }

}
6
Eren Yagdiran

Je sais qu'il a déjà été répondu à cette question ici, beaucoup de temps. Je veux toujours connaître les commentaires sur ma solution ici. J'ai essayé de construire le nombre d'enfants, car les contours passaient par l'entrée et tous les cas de test étaient réussis. 

namespace Hackerrank
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    class Program
    {
        static void Main(string[] args)
        {
            var tempArray = Console.ReadLine().Split(' ').Select(x => Convert.ToInt32(x)).ToList();
            int verticeNumber = tempArray[0];
            int edgeNumber = tempArray[1];

            Dictionary<int, int> childCount = new Dictionary<int, int>();

            Dictionary<int, int> parentDict = new Dictionary<int, int>();

            for (int count = 0; count < edgeNumber; count++)
            {
                var nodes = Console.ReadLine().Split(' ').Select(x => Convert.ToInt32(x)).ToList();
                var node1 = nodes[0];
                var node2 = nodes[1];

                if (childCount.ContainsKey(node2))
                    childCount[node2]++;
                else childCount.Add(node2, 1);

                var parent = node2;
                while (parentDict.ContainsKey(parent))
                {
                    var par = parentDict[parent];
                    childCount[par]++;
                    parent = par;
                }

                parentDict[node1] = node2;
            }

            Console.WriteLine(childCount.Count(x => x.Value % 2 == 1) - 1);
        }
    }
}
2
Swagata Prateek

Si vous observez l'entrée, vous pouvez constater qu'il est assez facile de compter le nombre de nœuds situés sous chaque nœud. Considérez (a b) comme entrée Edge, dans tous les cas, a est l'enfant et b est le parent immédiat. L'entrée a toujours des arêtes représentées de bas en haut. 

C'est donc essentiellement le nombre de nœuds qui ont un compte pair (à l'exclusion du nœud racine). J'ai soumis le code ci-dessous sur Hackerrank et tous les tests ont réussi. Je suppose que tous les cas de l’entrée satisfont à la règle. 

def find_edges(count):
    root = max(count)

    count_even = 0

    for cnt in count:
        if cnt % 2 == 0:
            count_even += 1

    if root % 2 == 0:
        count_even -= 1

    return count_even

def count_nodes(Edge_list, n, m):
    count = [1 for i in range(0, n)]

    for i in range(m-1,-1,-1):
        count[Edge_list[i][1]-1] += count[Edge_list[i][0]-1]

return find_edges(count)
2
doubleo

Ma première tendance est de travailler à partir des nœuds d'extrémité, car vous ne pouvez pas couper leurs arêtes car cela laisserait des sous-arbres à un sommet.

1
David Harkness

Voici l'approche que j'ai utilisée pour réussir tous les tests.

  1. Marquer le sommet 1 comme racine
  2. À partir du sommet de la racine actuel, considérez chaque enfant. Si la somme totale de l'enfant et de tous ses enfants est paire, vous pouvez couper ce bord
  3. Descendez au prochain sommet (enfant du sommet de la racine) et laissez-le être le nouveau sommet de la racine. Répétez l'étape 2 jusqu'à ce que vous ayez traversé tous les nœuds (recherche en profondeur d'abord).
1
kldavis4

Solution - Parcourez toutes les arêtes et comptez le nombre d'arêtes égales

Si nous supprimons un bord de l’arbre et qu’il en résulte deux arbres avec un nombre pair de sommets, appelons ce bord - même bord

Si nous supprimons un bord de l’arbre et qu’il en résulte deux arbres avec un nombre impair De sommets, appelons cela bord

Voici ma solution en rubis

num_vertices, num_edges = gets.chomp.split(' ').map { |e| e.to_i }
graph = Graph.new
(1..num_vertices).to_a.each do |vertex|
  graph.add_node_by_val(vertex)
end

num_edges.times do |Edge|
  first, second = gets.chomp.split(' ').map { |e| e.to_i }
  graph.add_Edge_by_val(first, second, 0, false)
end

even_edges = 0
graph.edges.each do |Edge|
  dup = graph.deep_dup
  first_tree = nil
  second_tree = nil
  subject_Edge = nil
  dup.edges.each do |e|
    if e.first.value == Edge.first.value && e.second.value == Edge.second.value
      subject_Edge = e
      first_tree = e.first
      second_tree = e.second
    end
  end
  dup.remove_Edge(subject_Edge)
  if first_tree.size.even? && second_tree.size.even?
    even_edges += 1
  end
end
puts even_edges

Note - Cliquez ici pour vérifier le code des classes Graph, Node et Edge

0
satnam

Voici les grandes lignes d'une approche alternative:

  1. Trouvez tous les points d'articulation dans le graphique.
  2. Vérifiez chaque point d'articulation pour voir si les arêtes peuvent y être supprimées.
  3. Supprimez les limites légales et recherchez plus de points d'articulation.
0
seaotternerd