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

来源:互联网 发布:下载输入法软件 编辑:程序博客网 时间:2024/05/01 21:25

问题描述

给定无向连通图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 <stdio.h>#include <stdlib.h>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开始。