计算搭积木是否能拼接成一个整体

题目描述:

一天,小明买了许多积木回家,他想把这些积木拼接在一起。每块积木有两个接口,每个接口我们用一个数字标记,规定只有当两块积木有相同数字标记的接口时,这两块积木才可以通过该接口拼接在一起。举例,有两块积木,接口数字分别为1,2和3,4,那么这两块积木无法拼接;若两块积木接口数字分别为1,2和2,3,那么这两块积木可以通过由数字2标记的接口拼接在一起。现在小明知道所有积木的数量和每块积木接口的数字标记,你能告诉他他可以将所有积木拼接成一个整体么?

输入描述

第一行一个整数t,表示测试数组组数1≤t≤10;

接下来在每组测试数据中:

第一行一个整数n,表示积木的数量1≤n≤100000,

下面n行每行2个整数x,y,表示其中一块积木的两个接口的数字标记;1≤x,y≤100000;

输出描述

对于每组测试数据,输出”YES”,表示该组数据中的所有积木可以拼接成一个整体,”NO”表示不行。(注意输出不包括引号)

样例输入

2
3
1 2
2 3
4 5
6
1 2
2 3
3 5
4 5
4 6
5 1

样例输出

NO
YES

题目来自于:https://www.acmcoder.com/#/practice/code

每一个积木都可以当作是一条边,接口则看作节点,若能连成一条有回路的环路或者无回路的连通图则结果为yes

数据结构中有对应结构, 欧拉路的概念如下,

欧拉通路 (欧拉迹):通过图中每条边且只通过一次,并且经过每一顶点的通路。

欧拉回路 (欧拉闭迹):通过图中每条边且只通过一次,并且经过每一顶点的回路。

简单说欧拉通路就是首尾不相接,而欧拉回路要求首尾相接。

无向图是否具有欧拉通路或回路的判定:(节点v的度是指和v相关联的边的数目)

欧拉通路:图连通;图中只有2个度为奇数的节点(就是欧拉通路的2个端点)

欧拉回路:图连通;图中所有节点度均为偶数

所以若能组成欧拉通路或欧拉回路即可以将所有积木拼接成一个整体

1、计算节点个数,对应添加数组对象,用于计算节点的度

2、计算每个节点的度

3、判断是否是欧拉通路或者欧拉回路

//arr = [[1,2],[2,3],[4,5]]
var printOut = function(arr){
  //1、节点去重添加到forarr内
  let blockarr = []
  arr.forEach(item=>{
    blockarr.push(...item);
  })
  blockarr=new Set(blockarr)
  //blockarr:[1,2,3,4,5]
  let forarr = {}
  blockarr.forEach(item=>{
    forarr[item]=[]
  })
  //forarr:{1:[],2:[],3:[]...}
  //2、计算每个节点的度
  arr.forEach(item=>{
    let flag1 = Object.keys(forarr).indexOf(JSON.stringify(item[0]))
    let flag2 = Object.keys(forarr).indexOf(JSON.stringify(item[1]))
    flag1>-1 && forarr[JSON.stringify(item[0])].push(item[1])
    flag2>-1 && forarr[JSON.stringify(item[1])].push(item[0])
  })
  console.log(forarr)
  //forarr:{1:[2],2:[1,3],3:[2],4:[5],5:[4]}
  //3、去重,
  Object.keys(forarr).forEach(item=>{
    forarr[item] = [...new Set(forarr[item])]
  })
  //判断是否是欧拉回路或者欧拉通路
  let res = Object.keys(forarr).filter(item=>{
    return forarr[item].length%2===1
  })
  console.log(res.length>2?'NO':'YES')
}
printOut([[1,2],[2,3],[4,5]])

结果:

//printOut([[1,2],[2,3],[4,5]])
NO
//printOut([[1,2],[2,3],[3,5],[4,5],[4,6],[5,6]])
YES

测试用例:

[[1,2],[2,3],[4,5]] no

[[1,2],[2,3],[3,5],[4,5],[4,6],[5,6]] yes

[[1,2],[2,3],[3,5],[4,5],[5,6],[4,2],[4,6]] no

[[1,2],[2,4],[4,6],[6,7],[8,9]] no

[[1,2],[2,4],[4,6],[6,7],[7,9]] yes

[[1,2],[2,3],[3,2],[2,3],[3,2],[6,4],[4,6]] no

[[1,2],[2,3],[2,4],[3,4]] yes

[[1,2],[2,3],[3,2],[2,3],[3,4],[6,4],[4,6]] yes

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值