华为机试 - 无向图染色
创始人
2024-03-22 08:51:12
0

目录

题目描述

输入描述

输出描述

用例

题目解析

算法源码


题目描述

给一个无向图染色,可以填红黑两种颜色,必须保证相邻两个节点不能同时为红色,输出有多少种不同的染色方案?

输入描述

第一行输入M(图中节点数) N(边数)

后续N行格式为:V1 V2表示一个V1到V2的边。

数据范围:1 <= M <= 15,0 <= N <= M * 3,不能保证所有节点都是连通的。

输出描述

输出一个数字表示染色方案的个数。

用例

输入4 4
1 2
2 4
3 4
1 3
输出7
说明

4个节点,4条边,1号节点和2号节点相连,

2号节点和4号节点相连,3号节点和4号节点相连,

1号节点和3号节点相连,

若想必须保证相邻两个节点不能同时为红色,总共7种方案。

题目解析

用例的染色方案,如下示意图:

相邻节点不能同时为红色

求一个连通图的染色方案,策略如下:
首先,必然有一种全黑方案。

 然后,我们找第一个点,即点1,找它的不相邻点,只有一个4,因此我们可以选择只给1染色,或者只给4染色,或者给1,4同时染色,这三个方案都符合要求

其实,这就是求1,4的全组合个数,即求 C(n,1) + C(n,2) + C(n,3) + ...... + C(n,n-1) + C(n,n) = (2^n) - 1

比如1,4有两个数,即一共有 (2^2) - 1 = 3 种。

按照上面这种策略,

继续找第二个点,即点2,其不相邻的只有点3,因此一共有(2^2) - 1 = 3 种染色方案

继续找第三个点,即点3,其不相邻的只有点2,因此一共有(2^2) - 1 = 3 种染色方案

继续找第四个点,即点4,其不相邻的只有点1,因此一共有(2^2) - 1 = 3 种染色方案

此时,我们发现除了全黑的染色方案外,一共有3*4 = 12种染色方案,但是实际上只有6种

整整多了一倍。

原因很简单,我们在统计第一个点的染色方案时,其实把第四个点的也统计了。统计第二个点时,把第三个点的染色方案也统计了。

因此后面对于第三个点和第四个点染色方案统计是重复的。 

因此,可得连通图的染色方案数目统计代码如下:

入参arr,即图中所有边 [v1, v2],

入参m,即图中点的数量

// 连通图的染色方案
function getDyeCount(arr, m) {const graph = {};for (let [v1, v2] of arr) {graph[v1] ? graph[v1].push(v2) : (graph[v1] = [v2]);graph[v2] ? graph[v2].push(v1) : (graph[v2] = [v1]);}let count = 0;for (let v in graph) {const n = m - graph[v].length;count += (1 << n) - 1; // (2 ^ n) - 1}return (count >>> 1) + 1; // +1 对应全黑染色方案,count >>> 1 即 count / 2
}

本题,到此还未结束,因为题目中有一句话:

不能保证所有节点都是连通的

这说明什么呢?即,可能会出现下面这种情况:

那么此时染色方案该如何统计呢?

题目和用例都没有说明清楚。。。。

我理解,应该统计每个连通分量的染色方案个数,然后求和作为题解。

即先统计1,2,3,4连通分量的染色方案个数为7,再统计5连通分量的染色方案为2,即一共有9个染色方案。

因此,本题还考察了连通分量的求解。

连通分量的求解可以使用并查集,关于并查集知识请看:华为机试 - 发广播_伏城之外的博客-CSDN博客 

算法源码

/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");const rl = readline.createInterface({input: process.stdin,output: process.stdout,
});const lines = [];
let m, n;
rl.on("line", (line) => {lines.push(line);if (lines.length === 1) {[m, n] = lines[0].split(" ").map(Number);}if (n !== undefined && lines.length === n + 1) {const arr = lines.slice(1).map((line) => line.split(" ").map(Number));console.log(getResult(arr, m));lines.length = 0;}
});/**** @param {*} arr 边,即[v1, v2]* @param {*} m 点数量*/
function getResult(arr, m) {const ufs = new UnionFindSet(m);for (let [v1, v2] of arr) {ufs.union(v1, v2);}const cates = {}; // cates对象每个属性对应一个连通分量for (let i = 1; i < ufs.fa.length; i++) {let fa = (ufs.fa[i] = ufs.find(i));cates[fa] ? cates[fa].push(i) : (cates[fa] = [i]);}let count = 0;for (let k in cates) {// 连通分量中点的个数const len = cates[k].length;const set = new Set(cates[k]);// 如果输入1~n+1行的边中还有连通分量中的点,则将边计入同一个连通图connect中const connected = arr.filter(([v1, v2]) => set.has(v1) || set.has(v2));// 求连通图的染色方案个数count += getDyeCount(connected, len);}return count;
}// 并查集
class UnionFindSet {constructor(n) {this.fa = new Array(n + 1).fill(0).map((_, i) => i);}find(x) {if (x !== this.fa[x]) {return (this.fa[x] = this.find(this.fa[x]));}return x;}union(x, y) {const x_fa = this.find(x);const y_fa = this.find(y);if (x_fa !== y_fa) {this.fa[y_fa] = x_fa;}}
}// 连通图的染色方案
function getDyeCount(arr, m) {const graph = {};for (let [v1, v2] of arr) {graph[v1] ? graph[v1].push(v2) : (graph[v1] = [v2]);graph[v2] ? graph[v2].push(v1) : (graph[v2] = [v1]);}let count = 0;for (let v in graph) {const n = m - graph[v].length;count += (1 << n) - 1; // (2 ^ n) - 1}return (count >>> 1) + 1; // +1 对应全黑染色方案,count >>> 1 即 count / 2
}

相关内容

热门资讯

新华社消息|三部重要法律案将提... 记者:魏冠宇、赵博 编导:季晓庄 新华社国内部 新华社音视频部 联合制作
北京公安机关十年共审查违法犯罪... 光明网记者 陈畅 孙满桃 创新推行“48小时速裁+不起诉案件快速办理+取保候审案件集中快审”三种模式...
河套合作区深圳园区条例获通过 12月26日上午,深圳市七届人大常委会第四十二次会议在举行第二次全体会议后闭幕。会议表决通过《深圳经...
依法严厉打击节日市场食品领域突... 2026年元旦、春节将至,节令食品和假期餐饮进入消费高峰期。为切实保障群众餐桌安全,公安部环境资源和...
连宿连淮高速开通 连云港市区高... 12月25日,连云港市召开“连宿”“连淮”高速公路建设工程开通运营暨市区部分高速公路路段差异化收费政...
四部门打出就业创业政策组合拳 ... 昨天,财政部等四部门出台指导意见,要求进一步发挥政府性融资担保体系增信分险作用,引导更多金融资源精准...
三部重要法律案将提请2026年... 新华社北京12月27日电(记者冯家顺)十四届全国人大常委会第十九次会议12月27日表决通过相关议案,...
演员保剑锋发布律师声明 12月26日,@保剑锋工作室 账号发布声明: 近期,部分网络用户在我方发布声明后仍持续、恶意散播关于...
一次性信用修复政策哪些情况能享... 极目新闻记者 刘闪 实习生 刘佳妮 12月22日,中国人民银行发布《关于实施一次性信用修复政策有关安...