Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 在一组项目之间建立排序的算法_Algorithm_Sorting_Graph Theory - Fatal编程技术网

Algorithm 在一组项目之间建立排序的算法

Algorithm 在一组项目之间建立排序的算法,algorithm,sorting,graph-theory,Algorithm,Sorting,Graph Theory,我有一组学生(为了一般性,在标题中称为项目)。在这些学生中,有些人以任性著称。我们被告知有一系列“我恨j”形式的仇恨关系“我恨j”并不意味着“j恨我”。我们应该把学生排成几行(最前面的一行编号为1),这样如果“我讨厌j”,那么我应该排成一行,严格地说,比j排的少(换句话说,在j排前面的某一行),这样我就不会向j扔东西(不允许向后翻)。找到所需最少行数(每行不需要相同数量的学生)的有效算法是什么 我们将作出以下假设: 1) 如果我们将其建模为有向图,那么图中就没有循环。最基本的循环是:如果“我恨j

我有一组学生(为了一般性,在标题中称为项目)。在这些学生中,有些人以任性著称。我们被告知有一系列“我恨j”形式的仇恨关系“我恨j”并不意味着“j恨我”。我们应该把学生排成几行(最前面的一行编号为1),这样如果“我讨厌j”,那么我应该排成一行,严格地说,比j排的少(换句话说,在j排前面的某一行),这样我就不会向j扔东西(不允许向后翻)。找到所需最少行数(每行不需要相同数量的学生)的有效算法是什么

我们将作出以下假设:

1) 如果我们将其建模为有向图,那么图中就没有循环。最基本的循环是:如果“我恨j”是真的,“j恨i”是假的。因为否则,我想订购就不可能了

2) 小组中的每个学生至少被另一个学生憎恨,或者至少憎恨另一个学生。当然,也会有一些学生既被某些人憎恨,又反过来憎恨其他学生。这意味着没有不构成图表一部分的流浪学生

更新:我已经考虑过用I-->j构建一个有向图,如果‘我讨厌j’并进行拓扑排序。然而,因为如果我必须将所有学生排在一行中,一般拓扑排序会更适合。因为这里的行有变化,所以我试图弄清楚如何将变化因素考虑到拓扑排序中,这样它就给出了我想要的

回答时,请说明解决方案的复杂性。如果有人在编写代码,而您不介意使用哪种语言,那么我更喜欢Java,但当然,任何其他语言都可以


JFYI这不是针对任何类型的家庭作业(顺便说一句,我不是学生。)。

我觉得你需要调查。

基本上,假设1中的重要一点是,这张图中不能有任何循环。如果存在任何循环,则无法解决此问题

首先,我会让所有不讨厌其他学生的学生坐在后排。然后你可以让讨厌这些学生的学生坐在下一排,以此类推。

简单答案=1排

把所有学生放在同一排

实际上,这可能无法解决所述的问题-较小的行,而不是相等的行

  • 把所有学生排在第一排
  • 对于每个仇恨关系,将不仇恨的学生排在仇恨的学生后面
  • 迭代直到没有活动,或者迭代Num(relation)次

  • 但我确信有更好的算法——看看非循环图。

    这个问题基本上是解决这个问题的另一种方法。行数实际上是路径中的节点数(边数+1)

    假设图为,则解决方案为。 你的假设1的非循环性更强一些。不仅A->B和B->A无效。还有A->B,B->C,C->A和任何长度的任何循环


    提示:问题是需要多少行,而不是哪一个学生在哪一行。这个问题的答案是最长路径的长度。

    它来自项目管理理论(或进度安排理论,我不知道确切的术语)。这里的任务是排序作业(顶点是作业,弧是作业顺序关系)

    显然,我们有一些无环的连通定向图。从顶点
    a
    到顶点
    b
    有一条弧,当且仅当
    a
    讨厌
    b
    。让我们假设有一个源(没有传入弧)和目标(没有传出弧)顶点。如果不是这样的话,就加上假想的。现在我们想要找到从源到目标的最长路径的长度(它将是行数-1,但请注意假想的顶点)

    我们将顶点秩(
    r[v]
    )定义为源和该顶点之间最长路径中的弧数
    v
    。显然,我们想知道
    r[目的地]
    。求秩的算法:

    0) r_0[v] := 0  for all verteces v
    repeat
    t) r_t[end(j)] := max( r_{t-1}[end(j)], r_{t-1}[start(j)] + 1 )  for all arcs j
    until for all arcs j r_{t+1}[end(j)] = r_t[end(j)]    // i.e. no changes on this iteration
    
    在每一步上,至少有一个顶点增加其秩。因此,在这种形式下,复杂性是O(n^3)

    顺便说一下,这个算法还提供了学生在行中的分布。把学生按他们各自的级别分组

    编辑:另一个具有相同想法的代码。也许这更容易理解

    # Python
    # V is a list of vertex indices, let it be something like V = range(N)
    # source has index 0, destination has index N-1
    # E is a list of edges, i.e. tuples of the form (start vertex, end vertex)
    R = [0] * len(V)
    do:
        changes = False
        for e in E:
            if R[e[1]] < R[e[0]] + 1:
                changes = True
                R[e[1]] = R[e[0]] + 1
    while changes
    # The answer is derived from value of R[N-1]
    
    #Python
    #V是顶点索引的列表,让它类似于V=range(N)
    #源具有索引0,目标具有索引N-1
    #E是边的列表,即形式的元组(起始顶点、结束顶点)
    R=[0]*len(V)
    做:
    更改=错误
    对于e中的e:
    如果R[e[1]]
    当然,这是最简单的实现。它可以被优化,并且时间估计可以更好


    Edit2:明显优化-仅更新与上一步更新的顶点相邻的顶点。也就是说,引入一个队列,队列中的顶点已更新。对于边存储,也应使用邻接列表。有了这样的优化,复杂性将是O(N^2)
    。实际上,每个顶点最多可以出现在队列中
    rank
    次。但顶点秩永远不会超过顶点数。因此,算法步骤的总数不会超过O(N^2)

    行数是有向图中最长路径的长度加上一。作为一种极限情况,如果没有仇恨关系,每个人都可以坐在同一排

    要分配行,请将所有不被
    S = set of students
    for s in S: s.row = -1        # initialize row field
    rownum = 0                    # start from first row below
    flag = true                   # when to finish
    while (flag):
      rownum = rownum + 1         # proceed to next row
      flag = false
      for s in S:
        if (s.row != -1) continue # already allocated
        ok = true
        foreach q in S:
          # Check if there is student q who will sit
          # on this or later row who hates s
          if ((q.row == -1 or q.row = rownum)
              and s hated by q) ok = false; break
        if (ok):                  # can put s here
          s.row = rownum
          flag = true
    
    postNodeCb( graph g, int node )
    {
        if ( /* No adj list */ )
            row[ node ] = 0;
        else
            row[ node ] = max( row number of all children ) + 1;
    }
    
    main()
    {
    .
    .
    
        for ( int i = 0; i < NUM_VER; i++ )
            if ( !visited[ i ] )
                graphTraverseDfs( g, i );`enter code here`
    .
    .
    }