题目意思: 给定n个节点,节点的编号为1-n,在给定m个节点链接的信息,现在要求对节点图色,只有两种颜色可以黑色和白色并且相邻的节点不能同时为黑色但是可以为白色,要求黑色节点最多的个数,以及一组节点的编号
解题思路: 对于节点而言,每一个节点就是两种情况,白色或黑色,那么我们知道这一个解空间树的每一层就是一个节点,那么我们只要去搜索这个解空间就可以了,这一题的数据虽然n到达100,但是真正的数据没那么大,不会超时。
注意事项: 这一题uva最后没有换行 , poj有换行,注意这个问题
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <cctype> #include <algorithm> using namespace std; const int MAXN = 110; //我们规定1是黑色 0是白色 int m, n, k; int G[MAXN][MAXN]; //矩阵 int ans[MAXN];//存储点的编号 int color[MAXN];//存储每个节点的颜色编号 int maximum;//最大的黑色的个数 //判断是否链接的两点是否颜色相反 int judge(int k) { for (int i = 1; i <= n; i++) { if (G[k][i]) { if (color[k] && color[i])//如果有两个链接的点的颜色相同那么就返回0 return 0; } } return 1; } //搜索 void dfs(int k) { if (k > n) { int max = 0; for (int j = 1; j <= n; j++) if (color[j]) ++max; if(max > maximum){//更新最优解 maximum = max; int t = 1; for(int j = 1 ; j <= n ; j++){ if(color[j]){ ans[t++] = j;//记录黑色的节点编号 } } } } if(k <= n){//递归求解节点 for (int i = 0; i <= 1; i++) {//两种颜色啊1 和 2 color[k] = i; if (judge(k)) dfs(k+1); color[k] = 0;//现场的恢复 } ++k;//下一个节点 } } // int main() { int x, y; scanf("%d", &m); while (m--) { memset(G, 0, sizeof (G)); memset(ans, 0, sizeof (ans)); memset(color , 0 , sizeof(color)); maximum = 0; scanf("%d%d", &n, &k); for (int i = 1; i <= k; i++) { scanf("%d%d", &x, &y); G[x][y] = 1;//邻接矩阵 G[y][x] = 1; } dfs(1); //输出结果 printf("%d\n", maximum);//输出最大值 int cnt = 0; for (int i = 1; i <= maximum; ++i) {//控制输出节点的编号 if (ans[i] && cnt == 1) printf(" %d", ans[i]); if (ans[i] && cnt == 0) { cnt = 1; printf("%d", ans[i]); } } printf("\n\n");//最后的换行还有空行 } return 0; }