
看到这一题我的第一个思路就是双向bfs
起点是a,终点还是a,但是flag是相反的("越"的方向)
tip1.可以用字典vis来存储flag
刚开始初始化时vissta,visend一个对应0、1
要求两个队列相接的时候flag要相同
tip2.get_nei函数
读取输入的时候用字典存储了点之间的关系
那么get_nei的时候就需要返回可能的下个节点以及new_flag
new_flag还是在bfs中判断,因为读取输入的时候是用0表示同向,1表示反向
tip3.存储中间过程
由于触碰点是起点和终点中间,所以我们需要记录前驱节点从而进行回溯
那么最适合的就是链表
python
from collections import deque,defaultdict
d=defaultdict(set)
n=int(input())
for i in range(n):
a,n1,b,n2=input().split()
if n1==n2:
d[a].add((b,0))
#明显不能双向:否则会Yu 1 Yuci 0 Yuci 0 Yu 0 = Yu 1 Yu 0
#d[b].add((a,0))#双向图?
else:
d[a].add((b,1))
#d[b].add((a,1))
def get_nei(cur):
neis=d[cur]
return neis
def bfs(k):
sta=end=k
staq=deque([sta])
endq=deque([end])
vissta={sta:1}#用0,1表示相对性
visend={end:0}
presta={sta:None}#记录前驱节点
preend={end:None}
while staq and endq:
ls=len(staq)
le=len(endq)
if ls<=le:
for _ in range(ls):#当前层
cur=staq.popleft()
flag=vissta[cur]
for nei,k in get_nei(cur): #解包
if k:
nflag= flag #0,1间取反
else:
nflag=not flag
if nei not in vissta:
vissta[nei]=nflag
staq.append(nei)
presta[nei]=cur
if nei in visend and visend[nei]==vissta[nei]:
return build_path(nei,presta,preend)
else:
for _ in range(le):
cur=endq.popleft()
flag=visend[cur]
for nei,k in get_nei(cur):
if k:
nflag=not flag #0,1间取反
else:
nflag=flag
if nei not in visend:
visend[nei]=nflag
endq.append(nei)
preend[nei]=cur
if nei in vissta and vissta[nei]==visend[nei]:
return build_path(nei,presta,preend)
return 0
def build_path(meet,presta,preend):
path_sta=[]
cur=meet
while cur is not None:#开始链表回溯
path_sta.append(cur)
cur=presta[cur]
path_sta.reverse()#掉头,方面后面衔接
path_end=[]
cur=preend[meet]
while cur is not None:
path_end.append(cur)
cur=preend[cur]
return path_sta+path_end
print(d)
for i in d:
k=bfs(i)
print(k)
'''不能dfs:不知道何时停止
def dfs()
'''
但是这段代码其实是错的
因为d[x]存的是x后面的节点,是单向的
所以无法从d[x]得到从终点返回的节点,只有d[k]=x遍历字典才能得到k,那还不如单向bfs
python
from collections import deque
from collections import defaultdict
d = defaultdict(list)
n = int(input())
for _ in range(n):
a, a_flag, b, b_flag = input().split()
a_flag = int(a_flag)
b_flag = int(b_flag)
d[(a, a_flag)].append((b, b_flag))
shortest_path = None
nodes = set()
for key in d:
nodes.add(key[0])
for b, _ in d[key]:
nodes.add(b)
nodes = list(nodes)
for sta in nodes:
for start_flag in [0, 1]:
target_flag = 1 - start_flag
vissta = {}
staq = deque()
staq.append((sta, start_flag, []))
vissta[(sta, start_flag)] = True
found = False
while staq and not found:
cur, flag, path_edges = staq.popleft()
if cur == sta and flag == target_flag:
if shortest_path is None or len(path_edges) < len(shortest_path):
shortest_path = path_edges
found = True
break
for (nei, nei_flag) in d.get((cur, flag), []):
if (nei, nei_flag) not in vissta:
vissta[(nei, nei_flag)] = True
new_path = path_edges + \
[(cur, flag, nei, nei_flag)]
staq.append((nei, nei_flag, new_path))
if found and len(shortest_path) == 0:
break
if shortest_path and len(shortest_path) == 0:
break
output_steps = []
for step in shortest_path:
a, a_flag, b, b_flag = step
output_steps.append(f"{a} {a_flag} {b} {b_flag}")
sta = shortest_path[0][0]
start_flag = shortest_path[0][1]
end_flag = 1 - start_flag
print(f"{' '.join(output_steps)} = {sta} {start_flag} {sta} {end_flag}")