如何在图形中找到3条边的负加权循环?

时间:2012-12-29 13:21:52

标签: c++ algorithm matlab graph cycle

我有一个有大约10,000个节点的有向图。所有边都是加权的。我想找到一个只包含3个边的负循环。有没有比O(n ^ 3)更快的算法?

示例代码:(g是我的图表)

if (DETAILS) std::printf  ("Calculating cycle of length 3.\n");
for (int i=0;i<NObjects;i++)
{
    for (int j=i+1;j<NObjects;j++)
    {
        for (int k=j+1;k<NObjects;k++)
        {
            if ((d= g[i][j]+g[j][k]+g[k][i])<0)
            {
                results[count][0] = i;
                results[count][1] = j;
                results[count][2] = k;
                results[count][3] = d;
                count++;
                if (count>=MAX_OUTPUT_SIZE3)
                    goto finish3;
            }

            if ((d= g[i][k]+g[k][j]+g[j][i])<0)
            {
                results[count][0] = j;
                results[count][1] = i;
                results[count][2] = k;
                results[count][3] = d;
                count++;
                if (count>=MAX_OUTPUT_SIZE3)
                    goto finish3;
            }
        }

    }
}
finish3:

1 个答案:

答案 0 :(得分:4)

我无法想到任何具有低于O(n 3 )的明确复杂度的算法,而且常数因子在实践中也很重要。以下算法允许修剪以加速找到具有负权重总和的长度为3的循环 - 或者检查没有这样的循环。

  1. 根据重量对(定向)边缘进行排序
  2. 以最低权重作为起始边缘。
  3. 尝试连接到起始边缘的末端顶点的所有边缘,其重量不低于起始边缘(第1次修剪),并在关闭循环时检查重量的总和。如果你找到一个带负数的周期,你就完成了。
  4. 继续使用具有下一个最低权重的边作为起始边。如果它的重量是负的转到3 - 否则你完成(第二次修剪)
  5. 这个想法是,具有负和的圆柱体的至少一个边缘必须具有负重量。并且我们可以在循环中以最低权重开始循环。

    如果你知道负权重的数字边是O(n)那么这个算法将是O(n 2 ld n),因为算法将由步骤1支配(=排序边缘根据其重量而定。)