C++回溯算法---图的m着色问题01

news2024/12/26 22:53:55

C++回溯算法---图的m着色问题

图的m着色问题是指给定一个图以及m种不同的颜色,尝试将每个节点涂上其中一种颜色,使得相邻的节点颜色不相同。这个问题可以转化为在解空间树中寻找可行解的问题,其中每个分支结点都有m个儿子结点,最底层有m的n次方个叶子结点。算法的思路是在解空间树中做深度优先搜索,并使用约束条件来剪枝优化搜索。

代码:

#include <iostream>
#include <cstring>
/*
*   图的m着色问题
*/
using namespace std;

const int maxn = 1005;
int G[maxn][maxn], color[maxn];//用于存储图中的边--用于存储每个节点的颜色 
int n, m; //n表示图中节点的数量,m表示可供选择的颜色数目。

bool ok(int u, int c) {
    for (int i = 1; i <= n; i++) {
        if (G[u][i] == 1 && color[i] == c)
            return false;
    }
    return true;
}

bool dfs(int u) {
    if (u > n)
        return true;
    for (int i = 1; i <= m; i++) {
        if (ok(u, i)) {
            color[u] = i;
            if (dfs(u + 1))
                return true;
            color[u] = 0;
        }
    }
    return false;
}

int main() {
    memset(G, 0, sizeof(G));//初始化邻接矩阵为0
    memset(color, 0, sizeof(color));//初始化颜色为0
    int e;//e表示图中边的数量
    cin >> n >> e >> m;
    for (int i = 0; i < e; i++) {
        int u, v;
        cin >> u >> v;
        G[u][v] = G[v][u] = 1;
    }

    if (dfs(1)) {
        cout << "Yes" << endl;
        for (int i = 1; i <= n; i++) {
            cout << "结点 " << i << " 的颜色为: " << color[i] << endl;
        }
    }
    else {
        cout << "No" << endl;
    }

    return 0;
}

分析:

这个算法的实现包括两个主要步骤:

  1. 判断颜色是否符合要求

对于每个节点 u,如果它与另一个节点 v 有边相连,且这两个节点颜色相同,那么就不能把节点 u 涂为该颜色。因此,需要定义一个函数 ok() 来判断某个节点染上某种颜色是否符合要求。具体来说,ok(u, c) 函数返回值为true表示节点 u 可以涂上颜色 c,否则返回false。

      2.使用深度优先搜索

使用深度优先搜索(DFS)从解空间树的根节点开始搜索,并在每个分支结点处调用 ok() 函数来剪枝。如果在整棵解空间树中找到了一组可行解,那么算法就停止搜索并输出结果。如果找不到任何一个可行解,则算法输出无解信息。

具体实现过程:

首先,需要定义一个二维数组 G[ ][ ],用于存储图中的边。其中,G[u][v] == 1 表示节点 u 和节点 v 之间有边相连,反之为 0。同时,还需要定义一个一维数组 color[ ],用于存储每个节点的颜色。

首先将所有边权赋值为 0,即不存在边。然后,读入所有边,将对应的边权赋值为 1。读入颜色数 m,并从节点 1 开始做深度优先搜索,依次尝试给每个节点涂上不同的颜色。在每个分支结点处,使用 ok() 函数来判断是否符合要求。如果染色成功,则继续对下一个节点做深度优先搜索。如果找到了一组可行解,则输出结果。

运行结果:


问题描述


 给定无向连通图G=(V, E)和m种不同的颜色,用这些颜色为图G的各顶点着色,每个顶点着一种颜色。是否有一种着色法使G中相邻的两个顶点有不同的颜色。这个问题是图的m可着色判定问题。若一个图最少需要m种颜色才能使图中每条边连接的两个顶点着不同颜色,则称这个数m为该图的色数。求一个图的色数m的问题称为图的m可着色优化问题。

例如:点个数n=7,颜色m=3的涂色方案

算法设计

 一般连通图的可着色问题,不仅限于可平面图。

 给定图G=(V,E)和m种颜色,如果该图不是m可着色,给出否定回答;若m可着色,找出所有不同着色方法。

算法思路
设图G=(V, E), |V|=n, 颜色数= m, 用邻接矩阵a表示G, 用整数1, 2…m来表示

m种不同的颜色。顶点i所着的颜色用x[i]表示。

问题的解向量可以表示为n元组x={ x[1],…,x[n] }. x[i]∈{1,2,…,m},

解空间树为排序树,是一棵n+1层的完全m叉树.

在解空间树中做深度优先搜索, 约束条件:如果a[j][i]=1 , x[i] ≠ x[j]
                                       

 m=3,n=3时的解空间树

再举个例子

对于下图,写出图着色算法得出一种着色方案的过程。

顶点数量n=4, 色数:m=3

 m=4,n=3时的解空间树

X[1]←1 , 返回 true
X[2]←1, 返回false; X[2]←2, 返回 true
X[3]←1 ,返回false; X[3]←2, 返回false;X[3]←3, 返回 true
X[4]←1, 返回false; X[4]←2, 返回false;X[4]←3, 返回 true

着色方案:(1,2,3,3)

复杂度分析

图m可着色问题的解空间树中,内结点个数是:

对于每一个内结点,在最坏情况下,用ok检查当前扩展结点每一个儿子的颜色可用性需耗时O(mn)。

因此,回溯法总的时间耗费是

在这里插入图片描述


#include"图的着色.h"


const int NUM = 100;
int n;//顶点数
int m;//颜色数
int a[NUM][NUM];//图的邻接矩阵
int x[NUM];//当前的解向量
int sum = 0;//解的数量

bool same(int t) {
    int i;
    for (i = 1; i < n; i++) {//修正同色判断函数的循环范围
        if ((a[t][i] == 1) && (x[i] == x[t]))
            return false;
    }
    return true;
}

void BackTrack(int t) {
    int i;
    if (t > n) {
        sum++;
        cout << "解" << sum << ":" << endl;//输出当前解的编号
        for (i = 1; i <= n; i++) {
            cout << x[i] << " ";//按照节点顺序输出颜色
        }
        cout << endl;
    }
    else
    {
        for (i = 1; i <= m; i++) {
            x[t] = i;
            if (same(t))
                BackTrack(t + 1);
            x[t] = 0;
        }
    }
}

int main() {
    cin >> n >> m;
    //初始化邻接矩阵为0
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            a[i][j] = 0;
        }
    }
    //读入边,构建邻接矩阵
    int u, v;
    while (cin >> u >> v) {
        if (u < 1 || u > n || v < 1 || v > n) {//判断输入是否合法
            cout << "输入不合法!" << endl;
            continue;
        }
        a[u - 1][v - 1] = 1;
        a[v - 1][u - 1] = 1;
    }

    BackTrack(1);//从第1个节点开始

    cout << "一共有" << sum << "个解。" << endl;//输出解的数量

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/425413.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Flink、Hudi技术选型

Flink CDC 2.2的优势 相比Flink1.x&#xff0c;2.x的版本有如下的特点&#xff1a; 1) 并发读取&#xff0c;全量数据的读取性能可以水平扩展。 2) 全程无锁&#xff0c;不对线上业务产生锁的风险。 3) 断点续传&#xff0c;支持全量阶段的 Checkpoint。 Flink SQL的优势 …

MongoDB学习

文章目录前言0 MongoDB和Redis区别1 简介MongoDB2 MongoDB的安装(需要使用Docker)3 MongoDB 概念解析3.1 数据库3 .2 文档3.3 集合3.4 MongoDB 数据类型3.5适用场景4 常用操作4.1 INSERT4.2 Query4.3 Update4.4 Remove4.5 aggregate4.6 索引5 整合Springboot使用5.1 导入依赖5.…

多比特信号跨时钟域同步处理

多比特信号跨时钟域同步处理 当在时钟域之间传递多比特数据时&#xff0c;普通的同步器并不能保证数据传递的安全性。在多时钟设计中&#xff0c;工程师往往容易犯一个错误&#xff0c;即同一事务处理含有需要从一个时钟域向另一个时钟域传递的多位跨时钟数据,并忽略了同步采样…

腾讯云物联网开发平台 LoRaWAN 透传接入 更新版

前言 之前有一篇文章介绍LoRaWAN透传数据&#xff0c;不过还是用物模型云端数据解析脚本&#xff0c;不是真正的透传。腾讯云物联网开发平台也支持对LoRaWAN原始数据的透传、转发。今天来介绍下。腾讯云 IoT Explorer 是腾讯云主推的一站式物联网开发平台&#xff0c;IoT 小能手…

大话数据结构-C(1)

一&#xff1a;数据结构绪论 1.1 数据&#xff1a; 描述客观事物的符号&#xff0c;计算机中可以操作的对象&#xff0c;能被计算机识别并输入给计算机处理的符号集合。 1.2 数据元素 是组成数据的、有一定意义的基本单位&#xff0c;在计算机中通常作为整体处理。也被称为记…

Linux系统如何设置开机自启脚本

Linux系统开启自启脚本的配置&#xff0c;我这里记录了三种办法&#xff0c;对于绝大多数linux系统&#xff0c;这三种方法里肯定有合适的。 1. 设置/etc/rc.local文件 /etc/rc.local文件是 /etc/rc.d/rc.local文件的软连接&#xff0c;rc.local文件本质上就是一个shell脚本 …

电商TO B背后:谁在重构产业带?

在这盘产业带大旗里&#xff0c;京东、淘宝、拼多多正在成为鲜活的新注解。 作者|思杭 编辑|皮爷 出品|产业家 有一座城&#xff0c;这里的百姓在40年前靠“鸡毛换糖”起家&#xff0c;他们聚集了全国各地的商品&#xff0c;再转卖出去。这样一来&#xff0c;就形成了销路…

金三银四最近一次面试,被阿里P8测开虐惨了.....

都说金三银四涨薪季&#xff0c;我是着急忙慌的准备简历——5年软件测试经验&#xff0c;可独立测试大型产品项目&#xff0c;熟悉项目测试流程...薪资要求&#xff1f;5年测试经验起码能要个20K吧 我加班肝了一页半简历&#xff0c;投出去一周&#xff0c;面试电话倒是不少&a…

itop-3568开发板驱动学习笔记(17)内核中断

《【北京迅为】itop-3568开发板驱动开发指南.pdf》 学习笔记 文章目录中断基础中断中断上下文中断号中断源类型内核中断 API获取中断号中断申请释放中断禁止中断使能中断实验程序中断基础 中断 CPU 在正常运行期间&#xff0c;由外部或者内部引起的事件&#xff0c;让 CPU 停下…

研报精选230411

目录 【行业230411华安证券】智能家居行业深度&#xff1a;ChatGPT等大模型催化智能家居行业进一步发展【行业230411信达证券】食品饮料行业2023年第12周周报&#xff1a;从当前时间点看今年液奶的投资机会【行业230411东方财富证券】食品饮料行业专题研究&#xff1a;BC两端需…

2023年信息安全推荐证书

随着网络安全行业的不断升温&#xff0c;相关的认证数量也不断增加&#xff0c;对于在网络安全行业发展的人才来说&#xff0c;提升职业竞争力最有效的办法之一&#xff0c;就是取得权威认证。 那么如何从繁多的适合网络安全从业者的证书中选择含金量高、发展潜力大的证书&…

Java分布式事务(七)

文章目录 🔥Seata提供XA模式实现分布式事务_业务说明🔥Seata提供XA模式实现分布式事务_下载启动Seata服务🔥Seata提供XA模式实现分布式事务_搭建聚合父工程构建🔥Seata提供XA模式实现分布式事务_转账功能实现上🔥Seata提供XA模式实现分布式事务_转账功能实现下🔥Se…

什么是车规级芯片?

目录 1、AEC-Q系列标准 2、ISO26262功能安全标准 芯片按照应用场景&#xff0c;通常可以分为消费级、工业级、车规级和军工级四个等级&#xff0c;其要求依次为&#xff1a;军工>车规>工业>消费。 车规级芯片&#xff0c;顾名思义&#xff0c;是应用到汽车中的芯片…

GMP调度

目录 A1 基础 协程 映射关系 N:1关系 1:1关系 M:N关系 概念 G M P go协程 GM模型 GMP模型 设计策略 复用线程 并行利用 抢占 全局G队列 "go func()"调度过程 ​编辑 特殊的M0和G0 M0 G0 Go调度器执行过程全解析 场景1 场景2 场景3 场景…

栈实现学生信息管理(C语言)

文章目录Stack.hmain.cStack.c用栈实现学生信息管理。这里放一下有哪些文件。Stack.h #pragma once防止库函数的重复引用&#xff0c;因为库函数会在预编译的时候在程序中展开&#xff0c;会增大程序的体积。   通过typedef对数据重命名&#xff0c;之后需要修改数据就十分方…

C/C++|物联网开发入门+项目实战|C语言基础|玩转c代码---从输入输出开始-学习笔记(6)

文章目录玩转c代码---从输入输出开始参考教程&#xff1a;C语言编程:一本全面的C语言入门教程&#xff08;第3版)第16章需要掌握的内容需要了解的内容常见的人机交互接口串口的输入输出PC常用的几个输入输出函数示例代码3 printf函数使用难点分析A.格式控制字符串的基本形式:示…

【毕业论文】| 基于Unity3D引擎的冒险游戏的设计与实现

&#x1f4e2;博客主页&#xff1a;肩匣与橘 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &#x1f4e2;本文由肩匣与橘编写&#xff0c;首发于CSDN&#x1f649; &#x1f4e2;生活依旧是美好而又温柔的&#xff0c;你也…

NVIDIA CUDA核函数编写注意事项之In-place

CUDA系列文章目录 文章目录CUDA系列文章目录前言总结参考资料前言 CUDA&#xff08;Compute Unified Device Architecture&#xff0c;统一计算架构&#xff09;是由NVIDIA所推出的一种集成技术&#xff0c;是其对于GPGPU&#xff08;A General-Purpose Graphics Processing U…

【源码解析】JDK 动态代理实现

基本流程 主方法 在该方法中&#xff0c;我们呈现了在日常使用 JDK 动态代理机制的方法。 public class VehicleDynamicProxy { /** * 被代理对象 */ public Vehicle targetVehicle; public VehicleDynamicProxy(Vehicle targetVehicle) { this.targetVehicle target…

注册中心要集成 SpringCloud实现负载均衡,需要哪些接口和规范?

前几天有个大兄弟问了我一个问题&#xff0c;注册中心要集成SpringCloud&#xff0c;想实现SpringCloud的负载均衡&#xff0c;需要实现哪些接口和规范。 既然这个兄弟问到我了&#xff0c;而我又刚好知道&#xff0c;这不得好好写一篇文章来回答这个问题&#xff0c;虽然在后面…