【题目描述】
给定无向连通图 G 和 M 种不同的颜色,用这些颜色为图 G 的各顶点着色,
每个顶点着一种颜色。如果有一种着色法使 G 中每条边的 2 个顶点着不同的颜
色,则称这个图是 M 可着色的。图的 M 着色问题是对于给定图 G 和 M 种颜色,
找出所有不同的着色法。
对于给定的无向连通图 G 和 M 种不同的颜色,编程计算图的所有不同的着色法。
【输入】
第一行有 3 个正整数 N,K 和 M,表示给定的图 G 有 N 个顶点和 K 条边,M 种
颜色。顶点编号为 1,2……,N。接下来的 K 行中,每行有 2 个正整数 U,V,
表示图 G 的一条边(U,V)。
数据范围:1<N<=100 1<K<=2500 1<M<=6
【输出】
不同的着色方案数
【样例输入】
5 8 4
1 2
1 3
1 4
2 3
2 4
2 5
3 4
4 5
【样例输出】
48
代码如下:
#include<iostream>
using namespace std;
class Color
{
friend void mcoloring(int n, int m, int** a);
private:
bool isUsed(int t);
void Backtrack(int i);
int n; //顶点数
int m; //颜色数
int** a; //邻接矩阵
int* x; //当前解
long sum; //方案数
};
bool Color::isUsed(int t)
{
for (int i = 1; i < t; i++)
if (a[i][t] == 1 && x[i] == x[t])
return false;
return true;
}
void Color::Backtrack(int i)
{
if (i > n)
{
sum++;
}
else
{
for (int j = 1; j <= m; j++)
{
x[i] = j;
if (isUsed(i))
Backtrack(i + 1);
x[i] = 0;
}
}
}
void mcoloring(int n, int m, int **a)
{
Color X;
X.n = n;
X.m = m;
X.a = a;
X.sum = 0;
int* p = new int[n+1];
for (int i = 1; i <= n; i++)
p[i] = 0;
X.x = p;
X.Backtrack(1);
delete[]p;
cout << X.sum;
}
int main()
{
int n, k, m;
cin >> n >> k >> m;
int k1, k2;
int** a = new int* [n+1];
for (int i = 1; i <= n; i++)
a[i] = new int[n + 1];
for (int i = 1; i <= k; i++)
{
cin >> k1 >> k2;
a[k1][k2] = 1;
}
mcoloring(n, m, a);
return 0;
}