Codeforces 题目传送门 & 洛谷题目传送门

本来说好的不做,结果今早又忍不住开了道题/qiao

我们称度为 \(1\) 的点为叶节点,度大于 \(1\) 的点为非叶节点。

首先考虑如何求出叶节点及其连边情况,这里不妨假设叶节点个数 \(\ge 3\)​,对于 \(\le 2\)​ 的情况特判掉,具体如何特判见下文。可以发现,对于两个非叶节点 \(x,y\)​,如果它们之间存在边相连,那么就一定存在两个点,到它们之间距离 \(\le 2\)​ 的点的集合恰好是 \(\{x,y\}\)​,具体构造就是取一个与 \(x\)​ 相连且 \(\ne y\)​ 的点,再取一个与 \(y\)​ 相连且 \(\ne x\)​ 的点。而如果存在两个点,满足它们交集恰好是 \(\{x,y\}\)​,那 \(x,y\)​ 之间必然存在边相连,否则如果 \(x,y\)​ 距离为 \(2\)​,那么这两点的交集中如果包含 \(x,y\)​,那么必然包含 \(x,y\)​ 的公共邻居,也就是 \(x,y\)​ 中间夹着的那个点,如果 \(x,y\)​ 距离为 \(3\)​,那么道理也是类似的,如果这两点的交集中如果包含 \(x,y\)​,那么必然包含 \(x,y\)​ 的之间的两个点,如果 \(x,y\) 距离 \(\ge 4\) 那么不可能存在两个点,到它们距离 \(\le 2\) 的点集中都包含 \(x,y\)​。这个可以使用 bitset 及其自带 _Find_first_Find_next 函数解决。

这样我们可以知道非叶节点之间的连边情况,接下来考虑如何将叶子挂上去。首先思考如何判断一个点是否对应一个叶节点的集合,显然对于一个非叶节点 \(x\) 及一个与其相连的叶节点 \(y\),必然有 \(y\) 对应的集合完全包含在 \(x\) 对应的集合中,这样我们遍历到一个点时,我们检验是否存在另一个集合完全包含在该集合中,如果有则跳过这个集合。这样可以保证我们遍历到的所有集合要么属于一个叶节点,要么属于一个不与任何点相连的非叶节点,对于后者而言显然不会对答案产生任何影响,因此我们不跳过它也罢。

接下来考虑如何判定一个叶节点的集合连向的是哪个非叶节点,我们去掉该集合中所有叶子节点(显然在第一步中我们已经知道哪些是叶子节点,而哪些不是),那么可以发现,去掉叶子节点后的集合,等于所有和与其相连的非叶节点的非叶节点组成的集合,而对于每个非叶节点,我们是知道哪些非叶节点与其相连的,这个同样可以 bitset 优化。

接下来找出这个非叶节点之后我们就可以知道所有与这个非叶节点相邻的叶节点了。具体方法就是找到这个集合中所有叶节点,显然这些叶节点都与这个非叶节点相邻。

这样我们就完美地处理了非叶节点个数 \(\ge 3\) 的情况,那如果非叶节点个数 \(\le 3\) 怎么办呢?

显然如果非叶节点个数 \(=1\),那么答案就是个菊花图,随便构造一个菊花图就行了。

如果非叶节点个数 \(=2\),那么所有叶子节点对应的集合大小都 \(<n\),而这种情况连向什么非叶节点是不重要的,因此我们仿照上面的过程,即对于一个叶子节点对应的集合,我们找出集合中所有叶子节点,那么这些叶子节点都应连向同一个非叶节点。

时间复杂度 \(\dfrac{n^3}{\omega}\)。

const int MAXN=1000;
int n;
bitset<MAXN+5> a[MAXN+5],b[MAXN+5],is;
int main(){
scanf("%d",&n);bool flg=1;
for(int i=1;i<=n;i++){
int len;scanf("%d",&len);flg&=(len==n);
while(len--){int x;scanf("%d",&x);a[i][x]=1;}
} if(flg){
for(int i=1;i<n;i++) printf("%d %d\n",i,n);
return 0;
} vector<pii> res;
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){
bitset<MAXN+5> tmp=a[i]&a[j];
if(tmp.count()==2){
int x=tmp._Find_first(),y=tmp._Find_next(x);
if(b[x][y]) continue;
b[x].set(y);b[y].set(x);is[x]=is[y]=1;
b[x][x]=b[y][y]=1;res.pb(mp(x,y));
}
} if(is.count()==2){
int r1=0,r2=0;
static int vis[MAXN+5];
for(int i=1;i<=n;i++) if(is[i]) (r1)?(r2=i):(r1=i);
for(int i=1;i<=n;i++) if(a[i].count()<n){
for(int j=1;j<=n;j++) if(!is[j]&&a[i][j]) vis[j]=1;
break;
}
for(int i=1;i<=n;i++) if(!is[i]){
if(vis[i]) res.pb(mp(r1,i));
else res.pb(mp(r2,i));
} for(pii e:res) printf("%d %d\n",e.fi,e.se);
} else {
static bool vis[MAXN+5];
for(int i=1;i<=n;i++){
bool flg=1;
for(int j=1;j<=n;j++) if((a[i]&a[j])==a[j]&&a[i]!=a[j])
flg=0;
if(!flg) continue;
bitset<MAXN+5> tmp=a[i]&is;
for(int j=1;j<=n;j++) if(tmp[j]&&b[j]==tmp){
if(!vis[j]){
for(int k=1;k<=n;k++) if(!is[k]&&a[i][k]) res.pb(mp(j,k));
vis[j]=1;
}
break;
}
} for(pii e:res) printf("%d %d\n",e.fi,e.se);
}
return 0;
}
/*
5
5 1 2 3 4 5
4 1 3 4 5
4 3 4 5 2
3 2 5 4
3 1 4 3
*/

Codeforces 566E - Restoring Map(bitset 优化构造)的更多相关文章

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

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

  2. @codefoces - 566E@ Restoring Map

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 对于一棵 n 个点的树,我们称两个点是相邻的当且仅当两个点的距离 ...

  3. Codeforces Round #207 (Div. 1) D - Bags and Coins 构造 + bitset优化dp + 分段查找优化空间

    D - Bags and Coins 思路:我们可以这样构造,最大的那个肯定是作为以一个树根,所以我们只要找到一个序列a1 + a2 + a3 .... + ak 并且ak为 所有点中最大的那个,那么 ...

  4. Codeforces 788C The Great Mixing(背包问题建模+bitset优化或BFS)

    [题目链接] http://codeforces.com/problemset/problem/788/C [题目大意] 给出一些浓度的饮料,要求调出n/1000浓度的饮料,问最少需要多少升饮料 [题 ...

  5. Axel and Marston in Bitland CodeForces - 782F (bitset优化)

    题目链接 $dp[0/1][i][x][y]$表示起始边为0/1, 走$2^i$ 步, 是否能从$x$走到$y$ 则有转移方程 $dp[z][i][x][y]\mid=dp[z][i-1][x][k] ...

  6. Codeforces Round #390 (Div. 2) E(bitset优化)

    题意就是一个给出2个字符矩阵,然后进行匹配,输出每个位置的匹配的结果 (超出的部分循环处理) 一种做法是使用fft,比较难写,所以没有写 这里使用一个暴力的做法,考虑到一共只出现26个字符 所以使用一 ...

  7. Codeforces 576D - Flights for Regular Customers(bitset 优化广义矩阵乘法)

    题面传送门 题意: 有一张 \(n\) 个点 \(m\) 条边的有向图,你初始在 \(1\) 号点,边上有边权 \(c_i\) 表示只有当你经过至少 \(c_i\) 条边的时候你才能经过第 \(i\) ...

  8. Codeforces 512E - Fox And Polygon(构造)

    Codeforces 题面传送门 & 洛谷题面传送门 中规中矩的构造题一道. 首先考虑将两张图都向一个中间状态转化.方便起见我们取所有点都连向 \(1\) 号点的情形作为中间状态. 考虑怎样从 ...

  9. hdu 5745 La Vie en rose DP + bitset优化

    http://acm.hdu.edu.cn/showproblem.php?pid=5745 这题好劲爆啊.dp容易想,但是要bitset优化,就想不到了. 先放一个tle的dp.复杂度O(n * m ...

随机推荐

  1. 【数据结构与算法Python版学习笔记】图——强连通分支

    互联网 我们关注一下互联网相关的非常巨大图: 由主机通过网线(或无线)连接而形成的图: 以及由网页通过超链接连接而形成的图. 网页形成的图 以网页(URI作为id)为顶点,网页内包含的超链接作为边,可 ...

  2. MacOS安装使用Kettle

    一.环境说明 操作系统版本:macOS Big Sur 11.6.1 机型:Intel版本 JDK版本:Amazon Corretto-openjdk8 Kettle版本:Kettle8.9 二.问题 ...

  3. 色彩滤镜矩阵(Color Filter Array)

    数码相机上的每个象素都带有一个光感应器,用以测量光线的明亮程度.由于光电二极管是只支持单颜色的装置,它不能区别不同波长的光线.因此,数码相机工程师在相机感应器的上部装上了一套镶嵌式的颜色滤镜,一个颜色 ...

  4. 如何系统学习C 语言(上)之 基础篇

    大话C 语言(一) 初识C 语言 老实说,上大学之前我根本不知道什么是C 语言,所以当初学校开设这门课时,我是充满了好奇,所以当初我翻阅了大量的C 语言入门书籍,千篇一律,都是从一些概念.术语和理论讲 ...

  5. 三、其他主机安装zabbix-agent加入到zabbix

    一.yum (rpm)方式 1,下载安装对应的zabbix-agent的rpm包 rpm -Uvh  https://repo.zabbix.com/zabbix/4.0/rhel/7/x86_64/ ...

  6. Qt Creator打造VScode one dark pro主题配色

    1.缘由 我之前习惯使用 vscode 进行开发,对 vscode 的 one dark pro 主题情有独钟.无奈公司需要使用 Qt Creator 进行日常开发,只能暂时舍弃 vscode,采用曲 ...

  7. GitHub 开源的小工具「GitHub 热点速览 v.21.45」

    作者:HelloGitHub-小鱼干 Copilot 是 GitHub 官方出品的代码自动补全工具,之前使用该工具需要有一定的要求.而本周靠 2k+ star 上热点的 copilot-docs 则是 ...

  8. 纯 CSS 自定义多行省略:从原理到实现

    文字溢出怎么展示,你的需求是什么?单行还是多行?截断,省略,自定义样式,自适应高度?在这里你都能找到答案.接下来我会由浅入深,从原理到实现,带你一步步揭开多行省略的面纱.我们先从最简单的单行溢出省略开 ...

  9. RedHat 7.0 Linux 下划分区,分区加密,配额,逻辑卷管理

    1:如何划分区: 1:明确分区的对象:xxx :fdisk /dev/xxx 2:增加一个分区:n:选择主分区或者扩展分区,"p" or "e" :默认地方开始 ...

  10. Linux&C———进程间通信

    管道和有名管道 消息队列 共享内存 信号 套接字 由于进程之间的并不会像线程那样共享地址空间和数据空间,所以进程之间就必须有自己特有的通信方式,这篇博客主要介绍自己了解到的几种进程之间的通信方式,内容 ...