C中的图形着色:无法识别逻辑错误

时间:2016-03-04 06:01:04

标签: c graph vertex

我正在尝试用C实现图着色算法,这个实现基于我们如何通过迭代邻接矩阵来分配颜色。在为第二个顶点指定颜色后,我无法得到它。

以下是我的程序代码:

int n, a[10][10], i, j, k, c[10], max = 0, col, ct = 0, rt = 0, m, count = 2;
void main() {
    printf("enter n\n");
    scanf("%d", &n);
    printf("enter the Adjacency Matrix for %d rows and %d columns\n", n, n);
    for (i = 0; i < n; i++) {
       c[i] = 0;
       for (j = 0; j < n; j++)
           scanf("%d", &a[i][j]);
    }
    c[0] = 1;
    c[1] = 2;
    for (i = 1; i < n; i++) {  
        for (j = 0; j < n; j++)
            if (a[i][j] > 0) {  
                m = 0;
                for (col = 0; col < n; col++) {
                    if (a[i][col] > 0)
                        rt++;
                    if (a[col][i] > 0)
                        ct++;
                }
                m = rt;
                if (ct > rt)
                    m = ct;
                if (m < 2) {
                    if (a[0][i] > 0)
                        c[i] = 2;
                    else
                        c[i] = 1;
                } else {
                    c[i] = count;
                    if (m > max) {
                        max = m;
                        count++;
                    }
                }    
                rt = 0;
                ct = 0;
            }
        if (c[i] < 1)
            if (c[i - 1] > 1)
                c[i] = 1;
            else
                c[i] = 2;
    }
    printf("The proper coloring is\n");
    for (i = 0; i < n; i++)
        printf("c%d=%d ", i + 1, c[i]);
    printf("\n");
}

示例输入: 考虑一个完整的图表:

0 1 1 1
1 0 1 1
1 1 0 1
1 1 1 0

预期产出:

c1=1 c2=2 c3=3 c4=4

观察输出:

c1=1 c2=2 c3=3 c4=3

2 个答案:

答案 0 :(得分:2)

错误似乎是逻辑错误,正如您可能通过问题标题的外观推断的那样。条件语句,您检查m是否大于max,然后相应地更新max和count似乎是不正确的。

我无法弄清楚预期的逻辑是什么,但我可以说出它为什么不正确。

在您的使用中,您保留在max中遇到的最大邻居数,并在找到具有更多邻居的顶点时更新它。有了它,你还可以更新计数,我认为它具有当前最高值的颜色。现在,除非您在每个步骤遇到一个包含更多邻居的顶点(在遍历每一行时),否则不会更新max,因此您不会更新计数。因此,除非遇到这样的顶点,否则不断为所遇到的所有顶点指定相同的当前最高计数。

您应该详细解释您实施的算法。但是,只要查看你的代码,我认为你至少应该在不同的地方增加数量。

一个好主意可能只是保持一个数组等于顶点的数量。然后对于每个顶点(在最外层循环内),您可以重置数组,并遍历i th 顶点的所有邻居,您可以设置它们中使用的颜色,并选择最小的未使用颜色。

这可能不是最有效的方法,但你已经有了一个O(n 3 )算法,所以我觉得这样做不会有什么坏处。

以下是您的代码,已更新以反映我提到的更改。

int n,a[10][10],i,j,k,c[10],max=0,col,ct=0,rt=0,m,count=2;
int used[11]; /* indices used are from 1 to n, inclusive */
void main()
{
    printf("enter n\n");
    scanf("%d",&n);
    printf("enter the Adjacency Matrix for %d rows and %d columns\n",n,n);   
    for(i=0; i < n ; i++)
    {
        c[i]=0;
        for(j=0;j<n;j++)
            scanf("%d",&a[i][j]);
    }
    c[0]=1;
    c[1]=2;
    for(i = 1 ;i < n;i++)
    {
        for(j = 1 ;j <= n ;j++)
            used[j] = 0;
        for(j = 0 ;j < i ;j++)
        {
            if(a[i][j] > 0)
                used[c[j]] = 1;
        }
        for(j = 1 ;j <= n ;j++)
            if(!used[j])
            {
                c[i] = j;
                break;
            }
    }
    printf("The proper coloring is\n");
    for(i = 0;i < n ;i++)
            printf("c%d=%d ",i+1,c[i]);
        printf("\n");
}

答案 1 :(得分:0)

为验证颜色着色的简单算法是什么样的?

  • 考虑循环中的所有顶点并指定颜色。已访问过的顶点已经有颜色;仍然会被访问的顶点仍然没有颜色。
  • 确定已经着色的相邻顶点使用哪些颜色。
  • 使用此信息,选择尽可能低的颜色。

您的算法是什么样的:

  • 将颜色1指定给顶点1,将颜色2指定给顶点2.(请注意,如果两个未连接,则顶点2可以使用与顶点1相同的颜色。)
  • 遍历所有剩余的顶点;然后循环遍历所有顶点。
  • 在另一个循环中计算到第二个顶点的传入和传出链接的数量。 (请注意,仅仅计算链接并不能提供有关哪些颜色仍然可用的信息。例如,您可以使用颜色3和4对许多顶点进行着色,但是您可以将新颜色基于链接数量。这个例子,颜色1将是一个不错的选择。)
  • 选择新颜色的标准是链接数是大于还是等于2.然后分配count,但在递增之前。这样你的例子就会得到第二个3,那里应该有4个。

所以你循环太多而且选择颜色的标准很差。您应该在相邻节点中保留已使用颜色的列表,并将新颜色基于该列表,而不是计算lonks。

您的代码存在其他风格问题:

  • 您的所有变量都应该是main的本地变量;没有理由让它们全球化,特别是因为你没有使用它们。
  • 请更加系统地使用变量声明。将它们全部打包在一个大的定义中,甚至会破坏数组和标量,使它们难以理解。
  • 请在所有代码块周围使用大括号,即使它们不是绝对必要的。它使得阅读代码更容易。内部区域中没有if的小else,例如if (ct > rt) m = ct;不需要大括号,但请考虑在其他地方使用它们。