@description@

对于一棵 n 个点的树,我们称两个点是相邻的当且仅当两个点的距离 <= 2。

现在给定 n 个集合,每一个集合表示树上某个点的相邻点是哪些。不过你不知道哪个集合对应哪个点。

现在这些集合构造出原树。保证至少存在一个解。如果多解,输出任意解即可。

原题传送门。

@solution@

两个点 x, y 对应的集合交集在树上仍然是一个连通块。

如果两个点 x, y 在树上距离 > 4,则它们集合交集为空。

如果两个点 x, y 在树上距离 = 4,则它们集合交集大小为 1。

如果两个点 x, y 在树上距离 = 3,则它们集合交集大小为 2。

如果两个点 x, y 在树上距离 = 2,则它们集合交集大小 >= 3。

如果两个点 x, y 在树上距离 = 1,则它们集合交集大小取决于 n:n = 2 时交集大小为 2;否则交集大小 >= 3。

集合交集为 2,该交集就对应着树上的一条边。

我们用 bitset 维护集合,并通过取交集找出所有的这种类型的边。

如果找不到一条这种类型的边,则只能是菊花图。特判即可。

否则,因为 n = 2 则已经找出了所有边,所以我们现在默认 n ≠ 2。

此时找出的边其实就是非叶结点之间形成的连通块,不妨称为新树。我们现在只需要把叶结点(度数为 1 的点)拼到父亲上面即可得到原树。

我们对于每个非叶结点,求出在新树中距离 <= 1 的点集,称为新邻集。

原图中叶结点原邻集 = 与该叶结点父亲相同的叶结点集合 + 父亲的新邻集。

如果新树只有一条边,此时两个点的新邻集相同,因此需要特判(父亲不同的叶结点分别连两个点)。

否则,每个点的新邻集互相不同。因此我们可以把原邻集与新树取交集,找到那个唯一的父亲。

不过注意到,当某个点在新树中度数为 1,此时它的原邻集与新树取交集也会对应一个新邻集。

此时该点一定连向某个原图中叶结点,且该叶结点的原邻集是该点的真子集。因此我们再判一下是否存在某个点的原邻集是当前点的原邻集的真子集即可。

复杂度 \(O(\frac{n^3}{\omega})\),实际上跑得挺快。

@accepted code@

#include <bitset>
#include <cstdio>
#include <algorithm>
using namespace std; int tag[1005], n;
bitset<1005>a[1005], b[1005], c[1005], t, p;
int main() {
scanf("%d", &n);
for(int i=1;i<=n;i++) {
int k, x; scanf("%d", &k);
for(int j=1;j<=k;j++)
scanf("%d", &x), b[i][x] = 1;
}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++) {
t = (b[i] & b[j]);
// printf("%d %d : %d\n", i, j, t.count());
if( t.count() == 2 ) {
int x = t._Find_first(); t[x] = 0;
int y = t._Find_first();
a[x][y] = a[y][x] = 1;
}
}
t = 0;
for(int i=1;i<=n;i++)
if( a[i].count() ) tag[i] = -1, t[i] = 1;
for(int i=1;i<=n;i++) a[i][i] = 1;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if( a[i][j] ) printf("%d %d\n", i, j);
if( t.count() == 0 ) {
for(int i=2;i<=n;i++)
printf("%d %d\n", 1, i);
}
else if( t.count() == 2 ) {
for(int x=1;x<=n;x++) {
for(int y=x+1;y<=n;y++) {
if( a[x][y] ) {
bool flag = false;
for(int i=1;i<=n;i++)
if( b[i].count() != n ) {
for(int j=1;j<=n;j++)
if( b[i][j] ) {
if( tag[j] == 1 ) break;
else if( tag[j] != -1 ) {
printf("%d %d\n", flag ? y : x, j);
tag[j] = 1;
}
}
flag = true;
}
}
}
}
}
else {
for(int i=1;i<=n;i++) {
c[i] = (b[i] & t);
bool flag = true;
for(int j=1;j<=n;j++)
if( b[i] == b[j] ) {
if( j < i ) {
flag = false;
break;
}
}
else if( (b[i] & b[j]) == b[j] ) {
flag = false;
break;
}
if( flag ) {
for(int j=1;j<=n;j++)
if( c[i] == a[j] ) {
for(int k=1;k<=n;k++)
if( b[i][k] && tag[k] == 0 )
printf("%d %d\n", j, k), tag[k] = 1;
break;
}
}
}
}
}

@details@

bitset 真好用。

一开始还想着二分图匹配找每个集合对应原树中哪一个点,不过发现找出来并不会更好做。

@codefoces - 566E@ Restoring Map的更多相关文章

  1. Codeforces.566E.Restoring Map(构造)

    题目链接 \(Description\) 对于一棵树,定义某个点的邻居集合为所有距离它不超过\(2\)的点的集合(包括它自己). 给定\(n\)及\(n\)个点的邻居集合,要求构造一棵\(n\)个点的 ...

  2. Codeforces 566E - Restoring Map(bitset 优化构造)

    Codeforces 题目传送门 & 洛谷题目传送门 本来说好的不做,结果今早又忍不住开了道题/qiao 我们称度为 \(1\) 的点为叶节点,度大于 \(1\) 的点为非叶节点. 首先考虑如 ...

  3. CF566E Restoring Map

    题意:乱序给你树上的每一个节点与之相距<=2的节点集合(并不知道这具体是哪个节点). 还原整棵树. 标程: #include<bits/stdc++.h> #define P pai ...

  4. WC2021 题目清单

    Day2 上午 <IOI题型与趣题分析> 来源 题目 完成情况 备注 IOI2002 Day1T1 Frog 已完成 IOI2002 Day1T2 Utopia IOI2002 Day1T ...

  5. Tree Restoring

    Tree Restoring Time limit : 2sec / Memory limit : 256MB Score : 700 points Problem Statement Aoki lo ...

  6. Backing Up and Restoring HBase Data

    There are two strategies for backing up HBase:1> Backing it up with a full cluster shutdown2> ...

  7. PatentTips – GPU Saving and Restoring Thread Group Operating State

    BACKGROUND OF THE INVENTION The present invention relates generally to single-instruction, multiple- ...

  8. mapreduce中一个map多个输入路径

    package duogemap; import java.io.IOException; import java.util.ArrayList; import java.util.List; imp ...

  9. .NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法

    .NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法 0x00 为什么需要Map(MapWhen)扩展 如果业务逻辑比较简单的话,一条主管道就够了,确实用不到 ...

随机推荐

  1. PG 更新统计信息

    http://blog.chinaunix.net/uid-24774106-id-3802225.html 一.vacuum的效果: 1.1释放,再利用 更新/删除的行所占据的磁盘空间. 第一点的原 ...

  2. mysql小白系列_07 锁与事务

    1.MySQL参数autocommit生产环境设1还是0?为什么? 2.MySQL参数tx_isolation生产环境上大多数是设什么值,为什么? 3.与MySQL锁相关的有哪些因素? 1.MySQL ...

  3. 当 RocketMQ 遇上 Serverless,会碰撞出怎样的火花?

    作者 | 元毅  阿里巴巴高级开发工程师 阿里巴巴云原生公众号后台回复 Knative,免费下载<Knative 云原生应用开发指南>电子书! 想必大家都比较了解 RocketMQ 消息服 ...

  4. 手机端页面访问PC页面自动跳手机端代码

    <script> var mobileAgent = new Array("iphone", "ipod", "ipad", & ...

  5. JavaScript变量语法扩展

    1.更新变量 一个变量被重新赋值后,它原有的值会被覆盖,变量值将会以最后一次赋值为准. 2.同时声明多个变量 var   age = 18 , address ='火影村' , gz = 2000 ; ...

  6. nginx 搭建图片服务器(windows 下,linux 下原理应该一样)

    作者的心声:很多知道的.用过的东西,不写下来,下次还要百度查询,浪费时间和精力,故本次写下学习笔记,方便下次查阅. 题外话:如有读者通过我这篇博客解决了工作上的难题,可以给个评论,让我一起分享你的喜悦 ...

  7. 浅谈SIEM

    一.概念 SIEM ( Security Information Event Management,安全信息与事件管理) Gartner的定义:安全信息和事件管理(SIEM)技术通过对来自各种事件和上 ...

  8. Black Hat Python之#1:制作简单的nc工具

    nc即netcat,是网络界的瑞士军刀.当入侵了一个服务器之后,发现nc工具已经被系统管理员移除之后,可以自己制作一个简单的客户端和服务器端来实现①上传文件②执行命令③开启一个新的命令行shell等几 ...

  9. Java并发编程 (三) 项目准备

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.案例环境初始化 1.环境搭建与准备 Spring Boot 项目,https://start.spr ...

  10. Java实现 蓝桥杯VIP 算法训练 筛选号码

    算法训练 筛选号码 Description 有n个人围成一圈,顺序排号(编号为1到n).从第1个人开始报数(从1到3报数),凡报到3的人退出圈子.从下一个人开始继续报数,直到剩下最后一个人,游戏结束. ...