| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- #!/usr/bin/env python3
- """课前零食:比较 BFS、0-1 BFS 与 Dijkstra 的取点顺序。"""
- from __future__ import annotations
- from collections import deque
- import heapq
- EDGES = [
- ("S", "A", 1), ("S", "B", 0), ("B", "A", 0),
- ("A", "T", 1), ("B", "T", 1), ("S", "C", 1), ("C", "T", 1),
- ]
- def ask(prompt: str, default: str) -> str:
- try:
- return input(prompt).strip() or default
- except EOFError:
- return default
- def graph() -> dict[str, list[tuple[str, int]]]:
- result: dict[str, list[tuple[str, int]]] = {}
- for u, v, weight in EDGES:
- result.setdefault(u, []).append((v, weight))
- result.setdefault(v, [])
- return result
- def zero_one_bfs(adj: dict[str, list[tuple[str, int]]]) -> None:
- dist = {u: float("inf") for u in adj}
- dist["S"] = 0
- work: deque[str] = deque(["S"])
- print("\n--- 0-1 BFS ---")
- while work:
- u = work.popleft()
- print(f"取出 {u},dist={dist[u]},双端队列={list(work)}")
- for v, weight in adj[u]:
- candidate = dist[u] + weight
- if candidate < dist[v]:
- old = dist[v]
- dist[v] = candidate
- if weight == 0:
- work.appendleft(v)
- place = "队首(0 边)"
- else:
- work.append(v)
- place = "队尾(1 边)"
- print(f" 松弛 {u}->{v}({weight}):{old} -> {candidate},放{place}")
- print("最终距离:", dist)
- def dijkstra(adj: dict[str, list[tuple[str, int]]]) -> None:
- dist = {u: float("inf") for u in adj}
- dist["S"] = 0
- heap: list[tuple[int, str]] = [(0, "S")]
- print("\n--- Dijkstra ---")
- while heap:
- current, u = heapq.heappop(heap)
- if current != dist[u]:
- print(f"弹出旧条目 ({current}, {u}),当前已是 {dist[u]},跳过。")
- continue
- print(f"定案候选 {u},距离 {current}")
- for v, weight in adj[u]:
- candidate = current + weight
- if candidate < dist[v]:
- old = dist[v]
- dist[v] = candidate
- heapq.heappush(heap, (candidate, v))
- print(f" 松弛 {u}->{v}({weight}):{old} -> {candidate},推入堆")
- print("最终距离:", dist)
- def bfs_unit_edges(adj: dict[str, list[tuple[str, int]]]) -> None:
- dist = {u: -1 for u in adj}
- dist["S"] = 0
- work: deque[str] = deque(["S"])
- print("\n--- 把每条边都当 1 的 BFS(仅作对照)---")
- while work:
- u = work.popleft()
- for v, _ in adj[u]:
- if dist[v] == -1:
- dist[v] = dist[u] + 1
- work.append(v)
- print("按边数得到:", dist)
- print("它把 S->A 当作 1 步最短,却看不见 S->B->A 的总权为 0。")
- def main() -> None:
- print("预设有向边:", ", ".join(f"{u}->{v}({w})" for u, v, w in EDGES))
- choice = ask("选择 b=BFS 对照、z=0-1 BFS、d=Dijkstra(回车为 z): ", "z").lower()
- adj = graph()
- if choice == "b":
- bfs_unit_edges(adj)
- elif choice == "d":
- dijkstra(adj)
- else:
- zero_one_bfs(adj)
- if __name__ == "__main__":
- main()
|