您的位置:首页 > 其它

P2819 图的m着色问题 洛谷

2017-03-26 11:41 267 查看

https://www.luogu.org/problem/show?pid=2819

题目背景

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

题目描述

对于给定的无向连通图G和m种不同的颜色,编程计算图的所有不同的着色法。

输入输出格式

输入格式:

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

输出格式:

程序运行结束时,将计算出的不同的着色方案数输出。

输入输出样例

输入样例#1:

5 8 4
1 2
1 3
1 4
2 3
2 4
2 5
3 4
4 5

输出样例#1:

48

说明

n<=100;k<=2500;

在n很大时保证k足够大。

保证答案不超过20000。

 

#include <algorithm>
#include <iostream>

using namespace std;

int n,k,m,fx,fy,ans;
int color[2505];
int burn[2505][2505];

bool judge(int x,int col)
{
//枚举每个点的染色情况
for(int i=1;i<=n;i++)
{
//不看当前点
if(x==i) continue;
//两个点首先要连接,如果颜色相同的话,那么就无法染编号为i的颜色
if(burn[x][i]==1&&color[i]==col)
return 0;
}
//两点不连接或者连到的点颜色不与编号为i的点的颜色相同,就可以染色
return 1;
}

void DFS(int now)
{
//如果当前染够了n个点,退出,找下一个方案;;
if(now==n+1)
{
ans++;
return ;
}
//枚举可以染上的颜色的编号
for(int i=1;i<=m;i++)
{
//如果当前的点没有染色,就判断它是否可以染编号为i的颜色
if(!color[now]&&(judge(now,i)))
{
//染上枚举到的颜色
color[now]=i;
//染下一个点
DFS(now+1);
//如果始终无法染够n个点,或者完成了一种方案,回溯;;
color[now]=0;
}
}
}

int main()
{
cin>>n>>k>>m;
for(int i=1;i<=k;i++)
{
cin>>fx>>fy;
//首先,把图建出来;;;
burn[fx][fy]=burn[fy][fx]=1;
}
DFS(1);
//从第一个点开始找;;
cout<<ans;
return 0;
}
带解析

 

无解析:

#include <algorithm>
#include <iostream>

using namespace std;

int n,k,m,fx,fy,ans;
int color[2505];
int burn[2505][2505];

bool judge(int x,int col)
{
for(int i=1;i<=n;i++)
{
if(x==i) continue;
if(burn[x][i]==1&&color[i]==col)
return 0;
}
return 1;
}

void DFS(int now)
{
if(now==n+1)
{
ans++;
return ;
}
for(int i=1;i<=m;i++)
{
if(!color[now]&&(judge(now,i)))
{
color[now]=i;
DFS(now+1);
color[now]=0;
}
}
}

int main()
{
cin>>n>>k>>m;
for(int i=1;i<=k;i++)
{
cin>>fx>>fy;
burn[fx][fy]=burn[fy][fx]=1;
}
DFS(1);
cout<<ans;
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: