图着色问题
图上的染色问题算是一个挺有名的NP-完全问题了吧
题目描述
给定无向连通图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
我的解析:
这道题是一道典型的搜索题,需要dfs和一点点优化(剪枝)。
我们来看一下样例给的这张图。
为什么是搜索?对于样例来说,每个点我们都有4种颜色可以选择,而在确定完一个点的颜色后又要选取其他点的颜色,并不能与它相连的点重复。于是马上想到要进行搜索。
搜索的过程:对于每个点,枚举它可能被染的颜色。如果与它相连的点颜色和它相同,那么就换下一个颜色;如果哪个颜色也不能选,那就回到上一个点换颜色(回溯)……
当确定完最后一个点的颜色后,这就是一个可行解,将答案增加1。
我们在判断哪个点与这个点(编号为n)连接并颜色相同时,本来是要遍历一遍图上的点的,而这样会超时。其实不需要这样做。只需遍历从编号1 到 编号n-1 的点就行了,因为
并没有确定编号n以后的点的颜色。这样相对于把点全遍历一遍,能更快一点,算是一个优化吧。
我的代码:
#include<cstdio> #include<algorithm> using namespace std; int m,n,k; int map[105][105]; int color[105]; int ans; void a(int p) { if(p == n+1) { ans++; return; } else { for(int i=1;i<=m;i++) { int mmp = false; for(int j=1;j<=p;j++) { if(map[p][j] == 1 && color[j] == i) { mmp = true; break; } } if(mmp == true) continue; color[p] = i; a(p+1); color[p] = 0; } } } int main() { // freopen("color.in","r",stdin); // freopen("color.out","w",stdout); scanf("%d%d%d",&n,&k,&m); for(int i=1;i<=k;i++) { int d1,d2; scanf("%d%d",&d1,&d2); map[d1][d2] = 1; map[d2][d1] = 1; } a(1); printf("%d",ans); return 0; }
posted on 2018-03-31 15:42 Ch_someone 阅读(5189) 评论(0) 编辑 收藏 举报