问题描述:
算法设计例题:图的m着色(回溯)
memory limit: 5000KB time limit: 2000MS
accept: 8 submit: 14
Description
给定无向连通图G和m种不同的颜色。用这些颜色为图G的各顶点着色,每个顶点着一种颜色。是否有一种着色法使G中每条边的2个顶点着不同颜色,求有多少种方法为图可m着色。
Input
输入的第一个为测试样例的个数T ( T < 120 ),接下来有T个测试样例。每个测试样例的第一行是顶点数n、边数M和可用颜色数m( n <= 10,M < 100,m <= 7 ),接下来M行,每行两个整数u和v,表示顶点u和v之间有一条边相连。( 1 <= u < v <= n )。
Output
对应每个测试样例输出两行,第一行格式为”Case #: W”,其中’#’表示第几个测试样例(从1开始计),W为可m着色方案数。
Sample Input
1
5 8 5
1 2
1 3
1 4
2 3
2 4
2 5
3 4
4 5
Sample Output
Case 1: 360
分析:
利用回溯法,即每个节点编列1~m,Color[cur]表示决策节点cur的颜色。如果出现矛盾则终止,否则决策cur++。全部节点决策完后,记录数ans++;
代码:
#include <iostream>
#include <string.h>
using namespace std;
const int MAXN = 15;
int c[MAXN][MAXN],Color[MAXN];
int n,M,m,T,ans;
int ok(int k);
void GraphColor(int cur,int m);
int main()
{
cin>>T;
int d=1;
while(T--)
{
memset(c,0,sizeof(c));
memset(Color,0,sizeof(Color));
ans =0;
cin>>n>>M>>m;
int i,a,b;
for(i=0;i<M;i++)
{
cin>>a>>b;
c[a][b]=1;
c[b][a]=1;
}
GraphColor(1,m);
cout<<"Case "<<d++<<":";
cout<<ans<<endl;
}
return 0;
}
void GraphColor(int cur,int m)
{
if(cur>n)
{
ans++;
return ;
}
for(int i=1;i<=m;i++)
{
Color[cur]=i;
int k=1;
if(!ok(cur))
k=0;
if(k)
GraphColor(cur+1,m);
}
}
int ok(int k)
{
for(int i=1;i<k;i++)
{
if(c[k][i]==1 && Color[i]==Color[k])
return 0;
}
return 1;
}