00-树多长出一条边.py 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. #!/usr/bin/env python3
  2. """课前零食:用队列剥离无向基环树或函数图的挂树。"""
  3. from __future__ import annotations
  4. from collections import defaultdict, deque
  5. UNDIRECTED = [("A", "B"), ("B", "C"), ("C", "A"), ("B", "D"), ("D", "E"), ("C", "F"), ("C", "G")]
  6. FUNCTIONAL = {"A": "B", "B": "C", "C": "A", "D": "C", "E": "D", "F": "E"}
  7. def ask(prompt: str, default: str) -> str:
  8. try:
  9. return input(prompt).strip() or default
  10. except EOFError:
  11. return default
  12. def undirected_lab() -> None:
  13. graph: dict[str, list[str]] = defaultdict(list)
  14. for u, v in UNDIRECTED:
  15. graph[u].append(v)
  16. graph[v].append(u)
  17. degree = {u: len(graph[u]) for u in graph}
  18. removed = {u: False for u in graph}
  19. queue: deque[str] = deque(u for u in graph if degree[u] == 1)
  20. print("边:", ", ".join(f"{u}-{v}" for u, v in UNDIRECTED))
  21. print("初始叶子:", list(queue))
  22. while queue:
  23. u = queue.popleft()
  24. removed[u] = True
  25. print(f"删掉叶子 {u},它一定不在环上。")
  26. for v in graph[u]:
  27. if not removed[v]:
  28. degree[v] -= 1
  29. print(f" {v} 的剩余度数变为 {degree[v]}")
  30. if degree[v] == 1:
  31. queue.append(v)
  32. print(f" {v} 新成为叶子,入队。")
  33. print("剩余环点:", sorted(u for u in graph if not removed[u]))
  34. def functional_lab() -> None:
  35. indegree = {u: 0 for u in FUNCTIONAL}
  36. for v in FUNCTIONAL.values():
  37. indegree[v] += 1
  38. queue: deque[str] = deque(u for u, value in indegree.items() if value == 0)
  39. removed: set[str] = set()
  40. print("箭头:", ", ".join(f"{u}->{v}" for u, v in FUNCTIONAL.items()))
  41. print("初始入度 0:", list(queue))
  42. while queue:
  43. u = queue.popleft()
  44. removed.add(u)
  45. v = FUNCTIONAL[u]
  46. indegree[v] -= 1
  47. print(f"删 {u},使 {v} 入度变为 {indegree[v]}")
  48. if indegree[v] == 0:
  49. queue.append(v)
  50. print(f" {v} 也不可能在环上,入队。")
  51. print("剩余有向环点:", sorted(set(FUNCTIONAL) - removed))
  52. def main() -> None:
  53. choice = ask("选择 u=无向基环树,f=函数图(回车为 u): ", "u").lower()
  54. if choice == "f":
  55. functional_lab()
  56. else:
  57. undirected_lab()
  58. if __name__ == "__main__":
  59. main()