相对论大师-记录型正负性质BFS/图论-链表/数据结构

看到这一题我的第一个思路就是双向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}")
相关推荐
明月看潮生15 分钟前
青少年编程与数学 02-019 Rust 编程基础 09课题、流程控制
开发语言·算法·青少年编程·rust·编程与数学
程序猿小三21 分钟前
python uv的了解与使用
开发语言·python·uv
oioihoii22 分钟前
C++23 views::slide (P2442R1) 深入解析
linux·算法·c++23
T0uken24 分钟前
【Python】UV:单脚本依赖管理
chrome·python·uv
yuhao__z43 分钟前
代码随想录算法训练营第六十三天| 图论9—卡码网47. 参加科学大会,94. 城市间货物运输 I
算法·图论
郭逍遥1 小时前
[工具]B站缓存工具箱 (By 郭逍遥)
windows·python·缓存·工具
alpszero1 小时前
YOLO11解决方案之物体模糊探索
人工智能·python·opencv·计算机视觉·yolo11
June`1 小时前
专题三:穷举vs暴搜vs深搜vs回溯vs剪枝(全排列)决策树与递归实现详解
c++·算法·深度优先·剪枝
vlln1 小时前
适应性神经树:当深度学习遇上决策树的“生长法则”
人工智能·深度学习·算法·决策树·机器学习
伊织code1 小时前
PyTorch API 6 - 编译、fft、fx、函数转换、调试、符号追踪
pytorch·python·ai·api·-·6