图着色问题(超详细!!!)

0x00 图着色问题

图着色问题(Graph Coloring Problem, GCP)又称着色问题,是最著名的NP-完全问题之一。

  • 图的m可着色判定问题

给定无向连通图Gm种不同的颜色。用这些颜色为图G的各顶点着色,每个顶点着一种颜色。是否有一种着色法使G中每条边的2个顶点着不同颜色。

  • 图的m可着色优化问题

若一个图最少需要m种颜色才能使图中每条边连接的2个顶点着不同颜色,则称这个数m为该图的色数。

0x01 图的m可着色判定问题

判定问题采用暴力dfs处理,对于当前的节点cur,其前面的节点已经着色过了,判断cur节点可以使用的颜色即可。如何判断cur节点可以使用的颜色呢?遍历所有颜色,判断当前颜色icur周围节点的颜色是不是不一样,如果是的话,那么可行;否则,不可行。

#include <iostream>
#include <cstring>
using namespace std;

const int N = 100, M = N * 2;
struct Edge {
    int to, next;
} edge[M];

int head[N], color[N], idx = -1;
int n, m, k;// n表示节点个数, m表示颜色个数,k表示数据个数
bool res = false;

void add(int u, int v) {
    edge[++idx].to = v;
    edge[idx].next = head[u];
    head[u] = idx;
}

//判断位置cur是否可以放入颜色i
bool check(int cur, int i) {
    for (int j = head[cur]; ~j; j = edge[j].next) {
        int son = edge[j].to;
        if (color[son] == i) return false;
    }
    return true;
}

void dfs(int cur) { //cur从0开始计算
    if (cur >= n) {
        res = true;
        return;
    }

    for (int i = 1; i <= m; i++) {
        if (check(cur, i)) {
            color[cur] = i;
            dfs(cur + 1);
        }
    }
}

另外上述代码稍加修改就可以计算方案个数。

#include <iostream>
#include <cstring>
using namespace std;

const int N = 100, M = N * 2;
struct Edge {
    int to, next;
} edge[M];

int head[N], color[N], idx = -1;
int n, m, k;
int res;

void add(int u, int v) {
    edge[++idx].to = v;
    edge[idx].next = head[u];
    head[u] = idx;
}

bool check(int cur, int i) {
    for (int j = head[cur]; ~j; j = edge[j].next) {
        int son = edge[j].to;
        if (color[son] == i) return false;
    }
    return true;
}

void dfs(int cur) {
    if (cur >= n) {
        res++;
        return;
    }

    for (int i = 1; i <= m; i++) {
        if (check(cur, i)) {
            color[cur] = i;
            dfs(cur + 1);
            color[cur] = 0;
        }
    }
}

0x02 图的m可着色优化问题

我在论坛上看到如下问题

元素=[1,2,3,4,5,6,7,8,9] 互斥=[(1,4),(2,5),(1,5),(5,6),(7,8),(3,9),(2,8),(4,5)]
把元素组成 N 个组, 保证互斥元素不在同一个组里, 并且 N 最小

这个问题实际上就是图的m可着色优化问题。

图的m可着色优化问题首先不难想到通过二分法(加上0x01中的方法)来做,但是这么做的话时间复杂度过高。可以直接采用dfs来处理。(为了处理简单,使用矩阵存储图)

每次判断当前数cur能不能放入之前的集合中,如果不能放入,那么新开辟一个集合;否则,放入即可。那么关键问题就是判定能否放入之前的集合中?将集合中的每个数存储,然后判断当前数cur和这些数是不是互斥即可。

#include <iostream>
#include <cstring>
using namespace std;

const int N = 100;
int cnt[N], num[N][N], g[N][N];//cnt表示每个集合中元素个数,num表示第i个集合中的第j个元素是谁,g表示关系图。
int n, k;// n表示节点个数,k表示数据个数
int res;

//判断第i个集合是不是可以放入cur(也就是i中的元素都不和cur互斥)
bool check(int cur, int i) {
    for (int j = cnt[i]; j > 0; --j) {
        if (g[num[i][j]][cur]) return false;
    }
    return true;
}

//将cur放入第s个集合中
void dfs(int cur, int s) { //cur从1开始计算
    if (s >= res) return;
    if (cur > n) {
        res = s;
        return ;
    }

    for (int i = 1; i <= s; i++) { 
        if (check(cur, i)) {
            num[i][++cnt[i]] = cur;
            dfs(cur + 1, s);
            num[i][cnt[i]--] = 0;
        }
    }
    s++;
    num[s][++cnt[s]] = cur;
    dfs(cur + 1, s);
    num[s][cnt[s]--] = 0;
}

reference:

https://baike.baidu.com/item/%E5%9B%BE%E7%9D%80%E8%89%B2%E9%97%AE%E9%A2%98/8928655?fr=aladdin

https://www.cnblogs.com/czsharecode/p/10558732.html

如有问题,希望大家指出!!!

### 回答1: 《OpenGL级宝典7》是一本关于OpenGL编程的权威教程,适合对OpenGL有一定了解并希望深入学习的读者。本书是PDF格式的,方便读者在电子设备上阅读和学习。 作为一本权威教材,《OpenGL级宝典7》详细介绍了OpenGL的各种技术和应用。它包含了丰富的实例和案例,从基础知识到高级应用都有涉及。读者可以学习到OpenGL的基本概念和原理,了解渲染管线、着色器、材质贴图、光照等核心技术,还可以学习到使用OpenGL实现3D图形、渲染技术和游戏开发等方面的知识。 《OpenGL级宝典7》采用了易于理解的方式来讲解复杂的OpenGL编程概念,配以大量图示和示例代码,使读者能够更好地理解和掌握。读者可以通过按部就班地学习,从简单到复杂逐渐提升自己的OpenGL编程技能。 这本书的优势在于其权威性和实用性。由于OpenGL作为一种跨平台的图形接口,广泛应用于游戏开发、科学可视化、虚拟现实等领域。掌握OpenGL编程技术,能够帮助读者开发出高效、流畅的图形应用程序。 总而言之,《OpenGL级宝典7》是一本值得推荐的OpenGL编程教程,能够帮助读者深入学习和掌握OpenGL的核心技术,并应用到实际项目中。无论是对于初学者还是有一定经验的开发者来说,这本书都是一本不可或缺的参考资料。 ### 回答2: OpenGL级宝典7是一本关于OpenGL图形编程的权威书籍,提供了全面且深入的知识内容。OpenGL是一种跨平台的图形库,用于开发各种类型的图形应用程序。 这本书主要分为以下几个部分:基础知识、图元绘制、颜色、透明度、光照和材质、纹理映射、投影和观察等。每个部分都详细介绍了相关的概念、API函数和实例应用。 通过学习这本书,读者可以了解OpenGL的基本概念和原理,掌握使用OpenGL进行图形渲染的方法和技巧。书中的例子清晰明了,配有详细的代码和展示效果,读者可以通过实际操作来加深理解。 此外,OpenGL级宝典7还介绍了一些高级的主题,如多重渲染目标、阴影和全局光照等。这些内容可以帮助读者扩展和深化对OpenGL的应用。 总之,OpenGL级宝典7是一本系统而全面的OpenGL图形编程参考书,适合想要学习和使用OpenGL进行图形编程的读者。无论是初学者还是有一定经验的开发者,都可以从中获得实用的知识和技巧,提升对图形编程的理解和能力。 ### 回答3: OpenGL级宝典是一本关于OpenGL图形编程的权威教材,其中的第七版是该系列中最新的版本。 这本书的PDF格式提供了便捷的电子阅读方式,使得读者可以随时随地地学习和查阅内容。通过这本书,读者可以系统地学习OpenGL的基础知识、高级概念和实际应用。 在这本书中,作者首先介绍了OpenGL的基本概念和工作流程,包括图形管线、顶点和片元着色器等。然后,他详细讲解了OpenGL的各种功能,如2D和3D图形的绘制、着色和光照、纹理映射、混合和渲染等。此外,还介绍了一些高级的技术,如几何着色器、计算着色器、阴影和后期处理。 除了理论知识,这本书还提供了丰富的示例代码和实践项目,让读者能够亲自动手实践。通过参考这些实例,读者可以更好地理解OpenGL的使用方法和技巧。 总的来说,OpenGL级宝典7 PDF是一个综合性的学习资源,适合想要学习OpenGL图形编程的初学者和有一定基础的开发者。它不仅提供了基础知识和高级概念的讲解,还有丰富的示例和实践项目,帮助读者更好地掌握和应用OpenGL技术。无论是通过纸质书籍还是电子PDF,读者都可以方便地获取这份宝贵的学习资料。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值