[BZOJ4466][Jsoi2013]超立方体

试题描述

超立方体是立方体在高维空间内的拓展(其在 \(2\) 维情况下退化为正方形,\(1\) 维情况下退化成线段)。在理论计算机科学领域里,超立方体往往可以和 \(2\) 进制编码联系到一起。对理论计算机科学颇有研究的 Will 自然也会对超立方体有着自己的思考。

上图就是在 \(0 \sim 4\) 维空间内超立方体所对应的图形。显然我们可以把超立方体的每个顶点看成一个点,每一条棱看成一条边,这样就会得到一个无向图,我们称之为超立方图。

\(D\) 维空间内的超立方图有 \(2^D\) 个点,我们把这些点从 \(0\) 到 \(2^D - 1\) 依次编号。

有一个有趣而重要的充要结论是:一定存在一种编号的方式,使得图中任意两个有边相连的顶点的编号的 2进制码中,恰好有一位不同。

在 \(2\) 维和 \(3\) 维空间内这个结论可以这样形象的理解:

对于 \(2\) 维空间,我们只要把这个正方形放到第一象限内,使得 \(4\) 个顶点的坐标按逆时针顺序依次为 \((0,0)\),\((1,0)\),\((1,1)\),\((0,1)\),然后再把坐标看成 \(2\) 位 \(2\) 进制数,依次将这 \(4\) 个点编号为 \(0\),\(1\),\(3\),\(2\) 即可。

对于 \(3\) 维空间,同样我们可以将立方体的一个顶点与原点重合,并使得所有棱均平行于坐标轴,然后分别确定这 \(8\) 个点的坐标,最后把 \(3\) 维空间内的坐标看成一个 \(3\) 位 \(2\) 进制数即可。对于 \(D\) 维空间,以此类推。

现在对于一个 \(N\) 个点 \(M\) 条边的无向图(每个点从 \(0\) 到 \(N-1\) 编号),Will 希望知道这个图是否同构于一个超立方图。

输入

第一行包含一个整数 \(Q\) 表示此数据中一共包含 \(Q\) 个询问。

接下来 \(Q\) 组询问,每一组询问的输入格式如下:

第一行包含两个整数 \(N\) 和 \(M\),接下来 \(M\) 行,每行 \(2\) 个不同的整数 \(x\),\(y\),表示图中存在一条无向边连接编号为 \(x\) 和 \(y\) 的点(\(0 \le x,y < N\))

输出

对于每一个询问分别输出一行,内容如下:

1、如果询问中给定的图不同构于任何一个超立方图,输出 \(-1\);

2、如果同构于某一个超立方图,那么请给图中这 \(N\) 个点重新编号,并在这一行输出 \(N\) 个用空格隔开的整数,表示原图中每个点新的编号,使得重新编号后,满足题目中所述的结论。

注意:输出文件的每一行,要么仅包含一个整数 \(-1\),要么则应包含一个由 \(0\) 到 \(N-1\) 这 \(N\) 个数组成的排列。如果有多组解输出任意一个均可。

输入示例

3
2 2
0 1
1 0
4 4
0 1
1 2
2 0
0 3
8 12
2 3
2 6
7 6
1 7
4 1
3 4
0 2
7 3
5 6
5 1
5 0
4 0

输出示例

-1
-1
0 6 1 5 4 2 3 7

数据规模及约定

\(Q \le 3,N \le 32768,M \le 1000000\)

题解

这题看上去有点吓人,但其实就是一个模拟,当然需要分析一些性质。

首先 \(N\) 必须是 \(2\) 整数次幂;\(M\) 也要满足一定条件,你可以一维一维地递推出 \(d\) 维下的超立方体有多少条棱,令 \(e_d\) 表示那个答案,则 \(e_0 = 0, e_i = 2e_{i-1} + 2^{i-1}\),判一下 \(M\) 是否等于 \(e_{\log N}\) 即可。(那个递推式的意思就是,\(d\) 维是由 \(d-1\) 的超立方体平移得到的,这样原来的棱数会倍增,同时每个点的平移轨迹会产生一条新棱,所以要加上 \(d-1\) 维时的点数)

然后随便规定一个点的标号为 \(0\),将其周围的点的编号依次设为 \(2^0, 2^1, 2^2, \cdots , 2^d\),然后开始 bfs,当搜到一个未确定标号的点时,若图合法则一定会后两个邻居标号已经确定(因为合法的图一定会有许多的四元环),那么就可以用这两个标号计算出它的标号。最后再检查一下是否符合题意。

中间有许多细节,实现时要注意。

然后还有一个问题就是为什么可以随便选一个点开始确定,这是因为立方体高度对称,它可以任意旋转;在 \(d\) 维的超立方体中,每个点出去一定都会有刚好 \(d\) 条互相垂直的棱,所以谁都能作为“坐标原点”,它连出去的边就是坐标轴了。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <cmath>
using namespace std;
#define rep(i, s, t) for(int i = (s), mi = (t); i <= mi; i++)
#define dwn(i, s, t) for(int i = (s), mi = (t); i >= mi; i--)int read() {int x = 0, f = 1; char c = getchar();while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }return x * f;
}#define maxn 32790
#define maxm 2000010int n, m, head[maxn], nxt[maxm], to[maxm], D;bool check_num(int n, int m) {int d = 0;while(!(n & 1)) n >>= 1, d++; D = d;if(n > 1) return 0;int e = 0, node = 1;rep(i, 1, d) e = (e << 1) + node, node <<= 1;if(m != e) return 0;return 1;
}void AddEdge(int a, int b) {to[m] = b; nxt[m] = head[a]; head[a] = m++;swap(a, b);to[m] = b; nxt[m] = head[a]; head[a] = m++;return ;
}int Q[maxn], hd, tl, tag[maxn];
bool vis[maxn], used[maxn];
int confirm(int u) {int v1 = -1, v2 = -1;for(int e = head[u]; e != -1; e = nxt[e]) if(vis[to[e]]) {if(v1 < 0) v1 = to[e];else{ v2 = to[e]; break; }}if(v2 < 0) return -1;int Xor = tag[v1] ^ tag[v2], cdiff = 0;rep(i, 0, D - 1) if(Xor >> i & 1) cdiff++;if(cdiff != 2) return -1;tag[u] = 0;rep(i, 0, D - 1) if(!(Xor >> i & 1)) tag[u] |= tag[v1] & (1 << i);if(!used[tag[u]]) return used[tag[u]] = 1, 0;// attempt 1tag[u] ^= Xor;if(!used[tag[u]]) return used[tag[u]] = 1, 0;tag[u] ^= Xor;// attempt 2int oXor = Xor;rep(i, 0, D - 1) if(Xor >> i & 1){ Xor ^= 1 << i; break; }tag[u] ^= Xor;if(!used[tag[u]]) return used[tag[u]] = 1, 0;tag[u] ^= Xor;// attempt 3Xor = oXor;dwn(i, D - 1, 0) if(Xor >> i & 1){ Xor ^= 1 << i; break; }tag[u] ^= Xor;if(!used[tag[u]]) return used[tag[u]] = 1, 0;// attempt 4return -1;
}
bool check() {rep(u, 0, n - 1) {for(int e = head[u]; e != -1; e = nxt[e]) {int Xor = tag[u] ^ tag[to[e]], cdiff = 0;rep(i, 0, D - 1) if(Xor >> i & 1) cdiff++;if(cdiff != 1) return 0;}}return 1;
}
void bfs() {hd = tl = 0; Q[++tl] = 0;tag[0] = 0; vis[0] = used[0] = 1;int c = 0;for(int e = head[0]; e != -1; e = nxt[e]) {if(!vis[to[e]]) vis[to[e]] = used[1<<c] = 1, Q[++tl] = to[e], tag[to[e]] = 1 << c;c++; if(c > D) return (void) puts("-1");}if(c != D) return (void)puts("-1");hd++;while(hd < tl) {int u = Q[++hd];c = 0;for(int e = head[u]; e != -1; e = nxt[e]) {if(!vis[to[e]]) {vis[to[e]] = 1; Q[++tl] = to[e];if(confirm(to[e]) == -1) return (void)puts("-1");}c++;}if(c != D) return (void)puts("-1");}rep(i, 0, n - 1) if(!vis[i]) return (void)puts("-1");if(!check()) return (void)puts("-1");rep(i, 0, n - 1) printf("%d%c", tag[i], i < n - 1 ? ' ' : '\n');return ;
}void work() {n = read(); int M = read();m = 0; memset(head, -1, sizeof(head));rep(i, 1, M) {int a = read(), b = read();AddEdge(a, b);}if(!check_num(n, M)) return (void)puts("-1");if(n == 1) return (void)puts("0");memset(vis, 0, sizeof(vis));memset(used, 0, sizeof(used));bfs();return ;
}int main() {int T = read();while(T--) work();return 0;
}

转载于:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/8485341.html

[BZOJ4466][Jsoi2013]超立方体相关推荐

  1. BZOJ 4466 [Jsoi2013]超立方体【模拟

    发现n维超立方体有2^n个定点,2^(n-1)*n条棱,每个点的度数为n 发现只有在二进制表示下 只有一位不同的两个点之间才有边 于是check上面那三个点可以先判断-1 用id[i] 表示 i 号点 ...

  2. War of Inazuma (Easy Version) 阅读理解-n维超立方体-二进制-longlong右移32位

    这个地方的地图可以被看作一个n维超立方体,有着恰好2n2^n2n个点.每个顶点编号从0到2n−12^n-12n−1.当且仅当两个顶点在二进制表示下仅有一位不同时这两个顶点相邻. 在战争中,每个点都被敌 ...

  3. bzoj4478: [Jsoi2013]侦探jyy 图论搜索

    bzoj4478: [Jsoi2013]侦探jyy Description JSOI 的世界里一共有 N 个不同的事件( 依次由 1 到 N 编号),以及 M 条线索. 每一条线索对应一个二元组(x, ...

  4. 【BZOJ4480】【JSOI2013】快乐的jyy(回文树)

    Description Solution 建出一个串的PAM,另一个串在上面跑,对于每个节点将第一个串的出现次数与第二个串的次数相乘即可. Code /************************ ...

  5. bzoj4479: [Jsoi2013]吃货jyy 欧拉回路+状态压缩Dp

    bzoj4479: [Jsoi2013]吃货jyy Description [故事背景] 作为JSOI的著名吃货,JYY的理想之一就是吃遍全世界的美食.要走遍全 世界当然需要不断的坐飞机了.而不同的航 ...

  6. 【花雕动手做】有趣好玩的音乐可视化系列小项目(26)--LED 超立方体

    偶然心血来潮,想要做一个声音可视化的系列专题.这个专题的难度有点高,涉及面也比较广泛,相关的FFT和FHT等算法也相当复杂,不过还是打算从最简单的开始,实际动手做做试验,耐心尝试一下各种方案,逐步积累 ...

  7. 监狱难题 位运算和超立方体染色

    原文链接: 监狱难题 位运算和超立方体染色 上一篇: Firefox 特性 svg mask 和clip-path的区别 下一篇: wasm 编译 cJSON 需要 安装CMAKE 3.18 视频和解 ...

  8. 超立方体的子平面(m-face of n-cube)

    这里的超立方体是n维立方体的意思,称为n-cube. 例如:3维立方体就是一个盒子,2维立方体就是个正方形面,1维立方体就是一个长为1的线段,0维立方体是一个点. m-face是立方体的平面. 例如: ...

  9. JZOJ 3158. 【JSOI2013】丢番图

    Description 丢番图 是亚历山大时期埃及著名的数学家.他是最早研究整数系数不定方程的数学家之一. 为了纪念他,这些方程一般被称作丢番图方程.最著名的丢番图方程之一是 xn+yn=znx^n+ ...

  10. Bzoj4480: [Jsoi2013]快乐的jyy 广义后缀自动机 倍增 哈希 manacher

    国际惯例的题面: 有人说这是回文自动机的板子题,然而我是不会这种东西的. 于是,我选择用更一般性的方法去解决这个题,就是那一堆东西了. 首先,我们把两个串同时插入一个广义SAM里,拓扑排序维护每个节点 ...

最新文章

  1. 前沿速递:Maven中央仓库新增依赖漏洞提醒功能
  2. C语言 NULL与0 对应的地址
  3. python pandas读取csv_Python3 pandas怎么读取csv文件的第一行的
  4. DL之Attention-ED:基于TF NMT利用带有Attention的 ED模型训练、测试(中英文平行语料库)实现将英文翻译为中文的LSTM翻译模型过程全记录
  5. 调用Com+时提示找不到文件
  6. CF-525E(E. Anya and Cubes) Meet-in-the-Middle
  7. 【数论想法题】小C的问题 @科林明伦杯哈尔滨理工大学第八届程序设计竞赛...
  8. nacos怎么修改服务分组_Nacos(六):多环境下如何“管理”及“隔离”配置和服务...
  9. java大数输出一位小数_java大数练习 大明A+B(大数小数的高精度)
  10. 并发编程之多线程操作
  11. 终于在五一之前打了SP3
  12. UI(用户界面)设计规则和规范
  13. php如何生成伪静态url,Thinkphp里关于U函数生成URL伪静态
  14. LaTeX 常用符号大全(from wikipedia)
  15. 新计算机的word无法输入文字,word打字后面的字消失怎么办
  16. 【胡侃系列】基于多元回归模型的双十一购物狂欢节天猫商城销售额预测
  17. 07年个人站长闯关,三条道路通罗马
  18. 音乐与计算机的交融,感受音乐交融之美
  19. 用户不在 sudoers 文件中此事将被报告
  20. HTML 设置背景图片自适应

热门文章

  1. 人工智能基础:人工智能云服务(Alaas)介绍
  2. Android技巧之相对高度使用
  3. Mac操作指南:Mac显示器颜色不正如何调节?
  4. 联想 thinkpad usb 移动硬盘 u盘 BIOS 启动 ubuntu 系统
  5. 基于GEE的bfastmonitor的改编
  6. 迅捷pdf转换器如何转换成word文档
  7. 华为MA5600配置radius认证登陆
  8. centos6使用devtoolset快速升级GCC版本4.8/5.2/8.3
  9. 【小峰の题单】网络流经典题目
  10. 计算任意多边形的面积(已知各顶点的坐标)