@codefoces - 566E@ Restoring Map
@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的更多相关文章
- Codeforces.566E.Restoring Map(构造)
题目链接 \(Description\) 对于一棵树,定义某个点的邻居集合为所有距离它不超过\(2\)的点的集合(包括它自己). 给定\(n\)及\(n\)个点的邻居集合,要求构造一棵\(n\)个点的 ...
- Codeforces 566E - Restoring Map(bitset 优化构造)
Codeforces 题目传送门 & 洛谷题目传送门 本来说好的不做,结果今早又忍不住开了道题/qiao 我们称度为 \(1\) 的点为叶节点,度大于 \(1\) 的点为非叶节点. 首先考虑如 ...
- CF566E Restoring Map
题意:乱序给你树上的每一个节点与之相距<=2的节点集合(并不知道这具体是哪个节点). 还原整棵树. 标程: #include<bits/stdc++.h> #define P pai ...
- WC2021 题目清单
Day2 上午 <IOI题型与趣题分析> 来源 题目 完成情况 备注 IOI2002 Day1T1 Frog 已完成 IOI2002 Day1T2 Utopia IOI2002 Day1T ...
- Tree Restoring
Tree Restoring Time limit : 2sec / Memory limit : 256MB Score : 700 points Problem Statement Aoki lo ...
- Backing Up and Restoring HBase Data
There are two strategies for backing up HBase:1> Backing it up with a full cluster shutdown2> ...
- PatentTips – GPU Saving and Restoring Thread Group Operating State
BACKGROUND OF THE INVENTION The present invention relates generally to single-instruction, multiple- ...
- mapreduce中一个map多个输入路径
package duogemap; import java.io.IOException; import java.util.ArrayList; import java.util.List; imp ...
- .NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法
.NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法 0x00 为什么需要Map(MapWhen)扩展 如果业务逻辑比较简单的话,一条主管道就够了,确实用不到 ...
随机推荐
- 基于 abp vNext 和 .NET Core 开发博客项目 - 接入GitHub,用JWT保护你的API
上一篇文章(https://www.cnblogs.com/meowv/p/12924859.html)再次把Swagger的使用进行了讲解,完成了对Swagger的分组.描述和开启小绿锁以进行身份的 ...
- Java通过循环结构和switch实现简易计算器
Java通过循环结构和switch实现简易计算器 可以循环计算,通过调用函数本身来实现重新计算 package com.shenxiaoyu.method; import java.util.Scan ...
- Pygame 框架安装教程(Python3.6为例)
1.python版本是3.6,最新的pygame是1.9.3,这两个最好都用32位的. pygame1.9.3下载地址:http://www.lfd.uci.edu/~gohlke/pythonlib ...
- 读Pyqt4教程,带你入门Pyqt4 _003
编程中的一个重要事情是布局管理,布局管理是如何在窗体上摆放窗口组件.可以有两种方式进行管理:绝对定位或使用布局类. 绝对定位 程序员用像素指定每个控件的位置和尺寸.使用绝对定位时,你必须理解几件事情. ...
- Linux、Ubuntu、CentOS安装和配置zsh
目录 01 zsh的安装 02 配置zsh 2.1 安装oh-my-zsh 2.2 查看oh-my-zsh目录 2.3 oh-my-zsh 插件的管理 2.3.1 添加插件 2.3.2 zsh-aut ...
- 【转】sql用逗号连接多张表对应哪个join?
逗号连接查询(用where连接条件): select order.id, order.orderdate,employee.id,employee.name from order,employee w ...
- 05 . Nginx的反向代理与负载均衡
Nginx负载均衡 客户端的访问都被代理到后端的一台服务器上,最终会出现性能瓶颈,从而导致效率降低,前端用户的访问速度急速下降,要解决这个问题就需要添加多台httpd,同时承受大量并发连接,每台服务器 ...
- jQuery-ajax请求使用
1.jQuery中的ajax $.ajax({ url:'地址', type:'get/post', data:{}, dataType:'json/jsonp', success:function( ...
- Chisel3 - 运算符和位宽推断
https://mp.weixin.qq.com/s/rI-CJM6GyI6EUHPZ3uYiFg 如同Verilog中的众多运算符,Chisel也针对自身的数据类型,提供了很多运算符. Ch ...
- Shell脚本 (二) 变量与运算符
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 四.Shell 中的变量 1.系统变量 1.1 常用系统变量 $HOME. $PWD. $SHELL . ...