正题

题目链接:https://www.luogu.com.cn/problem/P7920


题目大意

一个排列ppp生成的森林的形式如下,对于每个iii找到最大的j∈[1,i)j\in [1,i)j∈[1,i)满足 pi>pjp_i>p_jpi​>pj​,然后连一条i,ji,ji,j之间的边。
给出一张树GGG,求一个字典序最大的排列ppp使得生成的树与GGG同构。

1≤n≤50001\leq n\leq 50001≤n≤5000


解题思路

先考虑暴力的方法,我们可以枚举一个根,然后开始肯定根是111,然后子节点中假设大小都不相同我们肯定是从小到大放,因为假设现在放到kkk,那么每棵子树的根放的肯定是k−siz+1k-siz+1k−siz+1(因为一个根要是子树中最小的)。如果有大小相同的我们可以比较每棵内部放好时的字典序然后从大到小放。

显然这样是三方的,我们需要优化。考虑到我们每次需要比较子树的字典序大小,而对于所有根来说整棵就只有2n−22n-22n−2棵子树(每条边的正反方向的子树),我们可以把这些子树都拿出来比较。

先按照子树大小排序,然后我们按照子树大小从小到大排同大小子树的顺序,因为排大的子树时需要用到小子树的顺序关系。

而且不难观察到最优的根一定是与某个叶子连接的点,同样的这个叶子它的另一边是一个大小为n−1n-1n−1的子树,所以我们拿顺序最小的大小为n−1n-1n−1的子树出来输出即可。

时间复杂度:O(n2log⁡n)O(n^2\log n)O(n2logn),但是由于子树的字典序排序只会出现在同大小之间,所以常数很小,可以通过本题。


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cctype>
using namespace std;
const int N=1e4+10;
struct node{int id,siz;vector<int> v;
}p[N];
struct edge{int to,next,from;
}a[N];
int n,tot,ls[N],g[N],f[N],siz[N];
int read() {int x=0,f=1; char c=getchar();while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();return x*f;
}
bool cmp(int x,int y)
{return f[x]<f[y];}
bool cMp(node x,node y)
{return x.siz<y.siz;}
bool CmP(node x,node y){int l=min(x.v.size(),y.v.size());for(int i=0;i<l;i++)if(f[x.v[i]]!=f[y.v[i]])return f[x.v[i]]<f[y.v[i]];return 0;
}
void addl(int x,int y){a[++tot].to=y;a[tot].from=x;a[tot].next=ls[x];ls[x]=tot;return;
}
void dfs(int x,int fa){siz[x]=1;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa)continue;dfs(y,x);siz[x]+=siz[y];}return;}
void print(int x,int k){for(int i=0;i<p[x].v.size();i++){printf("%d ",k-p[g[p[x].v[i]]].siz+1);print(g[p[x].v[i]],k);k-=p[g[p[x].v[i]]].siz;}return;
}
int main()
{n=read();if(n==1)return puts("1")&0;for(int i=1;i<n;i++){int x=read(),y=read();addl(x,y);addl(y,x);}dfs(1,0);for(int z=1;z<=tot;z++){int x=a[z].from,y=a[z].to;p[z].siz=(siz[y]>siz[x])?(n-siz[x]):siz[y];for(int i=ls[y];i;i=a[i].next){int w=a[i].to;if(w==x)continue;p[z].v.push_back(i); }p[z].id=z;}sort(p+1,p+1+tot,cMp);int l=1,r=0,cnt=0;for(int S=2;S<n;S++){while(l<=tot&&p[l].siz<S)l++;while(r<tot&&p[r+1].siz<=S)r++;for(int x=l;x<=r;x++)sort(p[x].v.begin(),p[x].v.end(),cmp);sort(p+l,p+r+1,CmP);f[p[l].id]=++cnt;if(S==n-1)break;for(int x=l+1;x<=r;x++){cnt+=CmP(p[x-1],p[x]);f[p[x].id]=cnt;}}for(int i=1;i<=tot;i++)g[p[i].id]=i;printf("1 %d ",n);print(l,n-1);return 0;
}

P7920-[Kubic]Permutation相关推荐

  1. 【C++】C++11 STL算法(七):排列操作(Permutation operations)、数值操作(Numeric operations)

    排列操作(Permutation operations) 一.is_permutation 1.原型: template< class ForwardIt1, class ForwardIt2 ...

  2. LeetCode 76. Minimum Window Substring / 567. Permutation in String

    76. Minimum Window Substring 典型Sliding Window的问题,维护一个区间,当区间满足要求则进行比较选择较小的字串,重新修改start位置. 思路虽然不难,但是如何 ...

  3. R语言使用lmPerm包应用于线性模型的置换方法(置换检验、permutation tests)、使用lm模型构建简单线性回归模型、使用lmp函数生成置换检验回归分析模型

    R语言使用lmPerm包应用于线性模型的置换方法(置换检验.permutation tests).使用lm模型构建简单线性回归模型.使用lmp函数生成置换检验回归分析模型(Permutation te ...

  4. R语言使用coin包应用于独立性问题的置换检验(permutation tests、响应变量是否独立于组、两个数值变量是独立的吗、两个分类变量是独立的吗)、以及coin包的常用置换检验函数

    R语言使用coin包应用于独立性问题的置换检验(permutation tests.响应变量是否独立于组.两个数值变量是独立的吗.两个分类变量是独立的吗).以及coin包的常用置换检验函数 目录

  5. R语言使用coin包应用于独立性问题的置换检验(permutation tests)、使用普通cor.test函数和置换近似spearman_test函数、检验变量的相关性的显著性

    R语言使用coin包应用于独立性问题的置换检验(permutation tests).使用普通cor.test函数和置换近似spearman_test函数.检验变量的相关性的显著性(correlati ...

  6. R语言使用coin包应用于分类变量独立性问题的置换检验(permutation tests)、使用普通卡方检验chisq.test函数和置换近似卡方检验chisq.test函数、检验分类变量的独立性

    R语言使用coin包应用于分类变量独立性问题的置换检验(permutation tests).使用普通卡方检验chisq.test函数和置换近似卡方检验chisq.test函数.检验分类变量的独立性( ...

  7. R语言置换检验(permutation tests、响应变量是否独立于组、两个数值变量是独立的吗、两个分类变量是独立的吗)、置换检验的基本步骤、R语言自助法Bootstrapping计算置信区间

    R语言置换检验(permutation tests.响应变量是否独立于组.两个数值变量是独立的吗.两个分类变量是独立的吗).置换检验的基本步骤.R语言自助法Bootstrapping.自助法计算单个统 ...

  8. np.random.permutation

    np.random.permutation np.random.permutation():随机排列序列. 例1:对0-5之间的序列进行随机排序 例2:对一个list进行随机排序 多维度的咋回事? 来 ...

  9. 60 Permutation Sequence

    60 Permutation Sequence 题目 The set [1,2,3,-,n] contains a total of n! unique permutations.By listing ...

  10. Codeforces Beta Round #92 (Div. 1 Only) A. Prime Permutation 暴力

    A. Prime Permutation 题目连接: http://www.codeforces.com/contest/123/problem/A Description You are given ...

最新文章

  1. 代码重构的实战经验和那些坑
  2. 开发Windows Mobile和Wince(Windows Embedded CE)的部署项目(Deploy Project)时,如何修改注册表...
  3. 大型网站技术架构(一)大型网站架构演化
  4. ubuntu下安装psycopg2报错
  5. 金山毒霸免费Wifi独立版,只需一块无线网卡,完爆360随身wifi
  6. iOS锁屏代码注意使用新接口
  7. STM8S003F3使用总结——串口
  8. 亚马逊AWS图形界面登陆
  9. 【 许鹏-1021041305-安装单机版Swarm并试用】
  10. APKTOOL打包方法
  11. 后盾网ThinkPHP微博项目
  12. 思维方式 | 深入浅出解释“第一性原理”
  13. 毫秒数转换为时间计时天数
  14. test %eax %eax
  15. MVC 3.0 学习笔记(Razor CSHTML))
  16. 什么是jsp,它有什么用+jsp的本质是什么
  17. SpringBoot使用@Slf4j注解
  18. 十二个“一”的假想人物设定
  19. vue项目实战-去哪儿网
  20. 了解一下UiPath吗

热门文章

  1. mysql 调用未定义函数_php – Wierd和Annoying错误:调用未定义的函数mysql_query()[复制]...
  2. sql连接远程服务器索引超出了_手机怎么连接服务器远程桌面?RD client远程桌面使用教程...
  3. python柱状图挨在一起_echarts多个柱状图展示问题(bar都挤到一起了)
  4. 从mysql读取图片_如何从sql数据库内读取图片
  5. java使用zmodem_SecureCRT 中使用zmodem和Linux服务器交换文件
  6. 机器学习与气象数据_气象大数据与机器学习联合实验室 大数据和气象的“联姻”...
  7. lunixs 常用命令c语言,常用Lunix命令 - osc_271igh42的个人空间 - OSCHINA - 中文开源技术交流社区...
  8. 7-1 内存分区分配--首次适应算法 (100 分)
  9. 根据后序和中序求二叉树的层序
  10. 算法-排序-基数排序(对任意整数排序)