代码之家  ›  专栏  ›  技术社区  ›  Alisa Petrova

在有向图中更改一对顶点以创建循环

  •  0
  • Alisa Petrova  · 技术社区  · 5 月前

    我正在努力解决这个任务:

    新年时,学生们玩秘密圣诞老人。每个学生 i 给一个学生 a_i 他们必须送礼物给谁。游戏管理员给每个学生分配了自己的号码。但后来他的同事问:如果你从学生那里开始一系列礼物,这是真的吗 1 学生 a_1 ,然后依此类推,然后链条将与学生闭合 1. 在所有其他学生都参与其中一次之后?管理员不知道这是不是真的,但他将只更改一个 a_i number以获得适合其同事的配置。帮他解决这个问题。

    第一行包含一个自然数 n (2<=n<=10**5)学童人数。下一行包含 n 数字 a_i 带着号码去秘密圣诞老人那里的学生 (1<= a_i <=n

    输出的第一行应包含两个数字(1<=x,y<=n;x!=y)-带数字的学生 x 谁的 a_x 应该改变和新的价值 a_x 请注意 a_x != y 。如果存在多个答案,请打印任何答案。如果无法打印 -1 -1 .

    示例:

    输入:

    3
    1 2 3
    

    输出:

    -1 -1
    

    输入:

    3
    1 3 1
    

    输出:

    1 2
    

    我写了这段代码来解决这个任务:

    n = int(input())
    students = [int(x) for x in input().split()]
    a, b = -1, -1
    for x in range(1, n + 1):
        d = [x]
        vals = set()
        vals.add(x)
        for i in range(1, n + 1):
            val = students[d[i - 1] - 1]        
            d.append(val)        
            if val in vals: break   
            vals.add(val)     
        # print(f'x = {x} | d = {d}')
    
        if len(set(d)) == n:
            if d[-1] != d[0]:
                a = d[-2]
                b = d[0]
               
    print(a, b)
    

    我认为这基本上等同于发现是否存在一个距离循环一步之遥的图。

    代码似乎解决了我尝试的情况。然而,它并没有通过所有的测试。有人能帮忙指出这里可能出了什么问题吗?提前感谢。

    1 回复  |  直到 5 月前
        1
  •  0
  •   gnome    5 月前

    如果我从概念上正确理解了问题的定义,那么你就走对了路:你想看看是否有一个大小为的MST n-1 ,这样更改/添加一条边就会产生一个大小循环 n 换言之:

    • 如果你的MST有大小 n ,那么就没有什么可以改变的了(你的例子1就是这样一个例子,每个学生都会献出自己);
    • 如果您的MST大小< n-1 ,那么就没有什么可以更改的了,因为只允许更改一个配置;和
    • 如果你的MST有大小 n-1 ,那么就有了一个解决方案,因为你还有一个学生在当前MST中下落不明,你可以添加他们(在这种情况下,你的例子2落下)。在这种情况下,会出现多种解决方案,因为一个图可以有多个MST。

    总的来说,通过检查以下内容的大小,您可以快速失败 set(students) 。如果尺寸为 n-1 然后,你需要追踪谁获得了双重天赋,谁被排除在外。