相对论大师-记录型正负性质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}")
相关推荐
dying_man10 分钟前
LeetCode--24.两两交换链表中的结点
算法·leetcode
yours_Gabriel10 分钟前
【力扣】2434.使用机器人打印字典序最小的字符串
算法·leetcode·贪心算法
Mantanmu25 分钟前
Python训练day40
人工智能·python·机器学习
天天爱吃肉821828 分钟前
新能源汽车热管理核心技术解析:冬季续航提升40%的行业方案
android·python·嵌入式硬件·汽车
ss.li31 分钟前
TripGenie:畅游济南旅行规划助手:个人工作纪实(二十二)
javascript·人工智能·python
l木本I44 分钟前
大模型低秩微调技术 LoRA 深度解析与实践
python·深度学习·自然语言处理·lstm·transformer
哆啦A梦的口袋呀1 小时前
基于Python学习《Head First设计模式》第七章 适配器和外观模式
python·学习·设计模式
十月狐狸1 小时前
Python字符串进化史:从青涩到成熟的蜕变
python
草莓熊Lotso1 小时前
【数据结构初阶】--算法复杂度的深度解析
c语言·开发语言·数据结构·经验分享·笔记·其他·算法
KyollBM1 小时前
【CF】Day75——CF (Div. 2) B (数学 + 贪心) + CF 882 (Div. 2) C (01Trie | 区间最大异或和)
c语言·c++·算法