NOJ(1575)-回溯算法-图的m着色问题

问题描述

给定无向连通图G和m种不同的颜色。用这些颜色为图G的各顶点着色,每个顶点着一种颜色。如果有一种着色法使G中每条边的2个顶点着不同颜色,则称这个图是m可着色的。图的m着色问题是对于给定图G和m种颜色,找出所有不同的着色法。

输入

第1行有3个正整数n,r 和m(n < 20,r < 200,m < 10),表示给定的图G有n个顶点和r条边,m种颜色。顶点编号为0,1,2,…,n-1。接下来的k行中,每行有2个正整数u,v,表示图G 的一条边(u,v)。

输出

输出不同的着色方案的总数。

输入样例

3 2 2
0 1
1 2

输出样例

2

代码如下

#include 
#include 
int a[20][20],color[10];
int n, r, m,sum;
int check_color ( int k, int s )
{
    int i;
    for ( i = 0; i < n; i++ )
        if ( a[k][i] == 1 && color[i] == s )//有邻接关系并且着相同颜色
            return 0;
    return 1;
}

void put_color ( int k )
{
    int s;
    if ( k == n )//全部涂完
        sum++;
    else
    {
        for ( s = 1; s <= m; s++ )
            if ( check_color ( k, s ) )
            {
                color[k] = s;
                put_color ( k + 1 );
                color[k] = 0;
            }
    }
}

int main()
{
    int i, j, x, y;

    scanf ( "%d%d%d", &n, &r, &m );
    for ( i = 0; i < n; i++ )
        {
            for ( j = 0; j < n; j++ )
                a[i][j] = 0;
            color[i]=0;
        }
    for ( i = 0; i < r; i++ )
    {
        scanf ( "%d%d", &x, &y );
        a[x][y] = 1;
        a[y][x] = 1;
    }
    put_color ( 0 );
    printf("%d\n",sum);
    return 0;
}

总结

此题是回溯算法中十分经典的一道题,数组下标的处理是关键:
解题过程中用到了无向图的邻接矩阵的构造,将处于同一条边的两个顶底构成的数组元素标记为1,其他为0。
- 由于所有顶点的标记是从0开始的,所以构造邻接矩阵时一定也是从下标为0的地方开始,后面循环的时候,也要注意0这个位置。
- 主函数中第一次调用put_color函数也是从0开始,不能想当然从1开始。

你可能感兴趣的:(NOJ-回溯,C语言)