1757 – Sec

De la Universitas MediaWiki
Versiunea pentru tipărire nu mai este suportată și poate avea erori de randare. Vă rugăm să vă actualizați bookmarkurile browserului și să folosiți funcția implicită de tipărire a browserului.

În timp ce-și bea sortimentul preferat de vin sec, vrăjitorului Arpsod i-a venit în minte o problemă de informatică ce are un enunț cel puțin la fel de sec și anume:

Dându-se un arbore binar cu N noduri și rădăcina în nodul 1, să se răspundă la Q întrebări de forma: “sunt cei doi fii ai nodului X identici?”

Doi fii sunt identici dacă au același număr de subarbori și aceștia sunt identici (mai exact, pentru orice i=1, 2, ..., N subarborele i al primului este identic cu subarborele i al celui de-al doilea).

Cerința

Cunoscându-se arborele, să se răspundă la cele Q întrebări de forma indicată în enunţ.

Date de intrare

Pe prima linie a fișierului sec.in se află numărul natural N, reprezentând numărul de noduri ale arborelui. Următoarele N-1 linii conțin perechi de forma ( x, y ) cu semnificația că există muchie între nodul x și nodul y. Pe a (N+1)-a linie se va afla numărul natural Q, reprezentând numărul de întrebări. Pe următoarele Q linii se va afla câte un număr natural reprezentând eticheta nodului ai cărui fii vor fi analizați.

Date de ieșire

Fișierul sec.out va avea Q linii. Pe fiecare linie va fi scris cuvântul DA dacă cei doi fii sunt identici respectiv NU în caz contrar .

Restricții și precizări

  • 1 ≤ N ≤ 200.000
  • 1 ≤ Q ≤ 500.000
  • Nodurile arborelui sunt etichetate de la 1 la N.
  • Rădăcina va fi mereu în nodul 1.
  • Fii NU sunt identici dacă unul dintre ei trebuie oglindit / rotit pentru a arăta ca celălalt.
  • În cazul în care nodul cerut nu are fii, se va afișa DA (se consideră că sunt doi fii NULL identici)
  • Se garantează că pentru 30% din teste 1 ≤ N ≤ 1000 și 1 ≤ Q ≤ 3000

Exemplu:

sec.in

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

sec.out

NU
DA
NU
DA

Explicație

Nodurile 2, 7, 8, 9 au ambii fii identici. Celelalte noduri nu au aceasta proprietate

Rezolvare

from collections import defaultdict, deque
import hashlib
import sys

sys.setrecursionlimit(300000)

def read_input(file):
    with open(file, 'r') as f:
        data = f.read().split()
    index = 0
    N = int(data[index])
    index += 1
    edges = []
    for _ in range(N - 1):
        x = int(data[index])
        y = int(data[index + 1])
        index += 2
        edges.append((x, y))
    Q = int(data[index])
    index += 1
    queries = []
    for _ in range(Q):
        queries.append(int(data[index]))
        index += 1
    return N, edges, Q, queries

def build_tree(N, edges):
    tree = defaultdict(list)
    for x, y in edges:
        tree[x].append(y)
        tree[y].append(x)
    return tree

def dfs(node, parent, tree, hashes):
    children = []
    for child in tree[node]:
        if child != parent:
            children.append(dfs(child, node, tree, hashes))
    
    children.sort()
    subtree_hash = hashlib.sha256(''.join(children).encode()).hexdigest()
    hashes[node] = subtree_hash
    return subtree_hash

def solve(N, edges, Q, queries):
    tree = build_tree(N, edges)
    hashes = {}
    
    dfs(1, -1, tree, hashes)
    
    results = []
    for node in queries:
        children = [child for child in tree[node] if child != node]
        if len(children) < 2:
            results.append("DA")
        else:
            if hashes[children[0]] == hashes[children[1]]:
                results.append("DA")
            else:
                results.append("NU")
    
    return results

def write_output(file, results):
    with open(file, 'w') as f:
        for result in results:
            f.write(result + "\n")

def main():
    N, edges, Q, queries = read_input('sec.in')
    results = solve(N, edges, Q, queries)
    write_output('sec.out', results)

if __name__ == "__main__":
    main()