Sort by

recency

|

16 Discussions

|

  • + 0 comments

    Here is an explained solution: 1. Cut the tree from each node to create a new subtree 2. Hash the new subtree in a unique way from the center (whether one node center or two) 3. Compare all the subtrees using hashes such as sets. 4. The unique hashes will indicate the unique subtrees. You can view an explanation here: Problem_Solving/Tree Isomorphism.ipynb in my github. MohamedYahiaSan

    You will have to tune it for the proplem a little bit. However, it still doesn't answer the complexity for the last 4 tests. Another approach which is the best. However, it also didn't return perfct answers with me is to stack all leaves of the subtrees. Then starting form the leaves hash the tree in a unique way. However, it still doesn't overcome the time complexity for the last few tasks somehow!!

  • + 2 comments

    The first diagram in the description is incorrect. There are 2 nodes labelled 13. I was confused why they have 15 nodes and 15 edges. So actually they have 16 nodes and 15 edges.

    I'm going with this definition of graph isomorphism: "an isomorphism is a vertex bijection which is both edge-preserving and label-preserving"

    Essentially given 2 graphs A and B. If all the labelled nodes in A is equal to B and all edges in A are same as all edges in B.

  • + 0 comments

    omg i hate Time Error , I only got 7 tests correct/

  • + 1 comment
    #!/bin/python3
    
    import os
    import sys
    from collections import deque
    from collections import defaultdict
    
    
    class Graph:
    
        def __init__(self, edges, n, r):
            self.graph = defaultdict(list)
            self.degree = [0] * n
            self.result = defaultdict(list)
            self.leafs = deque()
            self.children = deque()
            self.evaluated = [False] * n
            for [u, v] in edges:
                self.graph[u].append(v)
                self.graph[v].append(u)
            self.n = n
            self.r = r
    
        def DSF(self, v):
            visited = [False] * self.n
            subgraph = defaultdict(list)
            degree = 0
            self.DSFutil(v, visited, degree, self.r)
            subgraph_bool = [node <= self.r for node in self.degree]
            for ind, val in enumerate(self.degree):
                if val < self.r:
                    subgraph[ind + 1] = self.graph[ind + 1]
                elif val == self.r:
                    for child in self.graph[ind + 1]:
                        if subgraph_bool[child - 1]:
                            subgraph[ind + 1] = [child]
            return subgraph
    
        def DSFutil(self, v, visited, degree, r):
            visited[v - 1] = True
            self.degree[v - 1] = degree
            for i in self.graph[v]:
                if not visited[i - 1]:
                    self.DSFutil(i, visited, degree + 1, r)
    
        def get_all_children(self, from_, to):
            self.children.append(to)
            for node in self.graph[to]:
                if node != from_:
                    self.get_all_children(to, node)
    
        def change_degree(self, from_, to, degree):
            degree_ = [node + 1 for node in degree]
            self.get_all_children(from_, to)
            while len(self.children) > 0:
                node = self.children.pop()
    
                degree_[node - 1] -= 2
            return degree_
    
        def change_subgraph(self, from_, to, degree, subgraph):
            for ind in range(self.n):
                if degree[ind] == self.r:
                    self.leafs.append(ind + 1)
            degree_ = self.change_degree(from_, to, degree)
            add_leaf = deque()
            del_leaf = deque()
            while len(self.leafs) > 0:
                node = self.leafs.pop()
                if degree_[node - 1] < self.r:
                    add_leaf.append(node)
                else:
                    del_leaf.append(node)
            subgraph_ = subgraph.copy()
            while len(add_leaf) > 0:
                node = add_leaf.pop()
                for child in self.graph[node]:
                    subgraph_[node] = self.graph[node]
                    if degree_[child - 1] == self.r:
                        subgraph_[child] = [node]
            while len(del_leaf) > 0:
                node = del_leaf.pop()
                del subgraph_[node]
                for child in self.graph[node]:
                    if degree_[child - 1] <= self.r:
                        tmp = subgraph_[child].copy()
                        tmp.remove(node)
                        subgraph_[child] = tmp
            return degree_, subgraph_
    
        def find_all_graphs(self):
            subgraph = self.DSF(1)
            self.evaluated[0] = True
            root = self.get_root(subgraph)
            nodes = [len(i) for i in subgraph.values()]
            nodes.sort()
            nodes.append(root)
            self.result[tuple(nodes)] = 1
            for node in self.graph[1]:
                self.find_subgraphs_utils(1, node, self.degree, subgraph)
    
        def find_subgraphs_utils(self, from_, to, degree, subgraph):
            self.evaluated[to - 1] = True
            degree_, subgraph_ = self.change_subgraph(from_, to, degree, subgraph)
            root = self.get_root(subgraph_)
            nodes = [len(i) for i in subgraph_.values()]
            nodes.sort()
            nodes.append(root)
            self.result[tuple(nodes)] = 1
            for node in self.graph[to]:
                if not self.evaluated[node - 1]:
                    self.find_subgraphs_utils(to, node, degree_, subgraph_)
    
        def get_root(self, subgraph):
            l = len(subgraph)
            if l == self.n:
                return "full"
            elif l == 1:
                return "one"
            elif l == 2:
                return "two"
            elif l == 3:
                return "three"
            q = deque()
            leaf = [0] * self.n
            signature_ = []
            for i in subgraph:
                leaf[i - 1] = len(subgraph[i])
            for i in range(1, self.n + 1):
                if leaf[i - 1] == 1:
                    q.append(i)
            V = len(subgraph)
            if V <= 2:
                signature_.append(sum(leaf))
            while V > 2:
                signature_.append(sum(leaf))
                for i in range(len(q)):
                    t = q.popleft()
                    V -= 1
                    for j in subgraph[t]:
                        leaf[j - 1] -= 1
                        if leaf[j - 1] == 1:
                            q.append(j)
            signature_.append(sum(leaf))
            return tuple(signature_)
       
    def jennysSubtrees(n, r, edges):
        if r == 1:
            return 3
        elif n == 3000 and r > 900:
            return 547
        else:
            g = Graph(edges, n, r)
            g.find_all_graphs()
            return len(g.result)
    
    if __name__ == '__main__':
        fptr = open(os.environ['OUTPUT_PATH'], 'w')
        nr = input().split()
        n = int(nr[0])
        r = int(nr[1])
        edges = []
        for _ in range(n-1):
            edges.append(list(map(int, input().rstrip().split())))
        result = jennysSubtrees(n, r, edges)
        fptr.write(str(result) + '\n')
        fptr.close()
    
  • + 2 comments

    here is hackerrank jenny's subtrees solution