题面

题解

这道题由于是求字典序最小的,所以要贪心地枚举数字,然后找可以走到的编号最小的点,处理这条路径。

这条路径有一些特性。

以下是特别精炼的结论:

所以一旦选好了路径,这些边的先后顺序就被定死了,后面的路径肯定不能与他冲突

于是我们只要记录边的先后关系,然后进行非常严密的逻辑判断选择一条不冲突的路径。

复杂度O(n^2)

Code

你们看不懂的

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<stack>
#include<algorithm>
#define LL long long
using namespace std;
int read() {
int f = 1,x = 0;char s = getchar();
while(s < '0' || s > '9') {if(s == '-')f = -1;s = getchar();}
while(s >= '0' && s <= '9') {x = x * 10 + s - '0';s = getchar();}
return x * f;
}
struct ed{
int v,id;
ed(){}
ed(int V,int I){v = V;id = I;}
};
vector<ed> g[2005];
int id[2005];
int pre[8005],suf[8005];
int fa[8005];
int le[8005];
int minn;
int find(int x) {
if(fa[x] != x) fa[x] = find(fa[x]);
return fa[x];
}
void unionSet(int a,int b) {
int u = find(a),v = find(b);
if(u < v) le[u] += le[v],fa[v] = u;
else le[v] += le[u],fa[u] = v;
}
int n,m,i,j,s,o,k;
void dfs(int x,int fat,int fai) {
if(fai != 0 && (((find(fai) > n || le[find(fai)] == g[x].size()) && !suf[fai] && !pre[x + n]) || g[x].size() == 1)) minn = min(minn,x);
// printf("minn:%d x:%d find[%d]:%d\n",minn,x,fai,find(fai));
for(int i = 0;i < g[x].size();i ++) {
int y = g[x][i].v,z = g[x][i].id;
if((fai == 0 && (((find(z) > 2*n || le[find(z)] == g[x].size()) && !pre[z] && !suf[x]) || g[x].size() == 1)) || (y != fat && !pre[z] && !suf[fai] && find(fai) != find(z) && !(find(fai) <= n && find(z) <= 2*n && le[find(fai)] + le[find(z)] != g[x].size()))) {
int zi = z;
if(zi <= 3 * n) zi += n;
else zi -= n;
dfs(g[x][i].v,x,zi);
}
}
return ;
}
bool dfs2(int x,int fat,int mini,int fai) {
if(x == mini) {
suf[fai] = x + n;
pre[x + n] = fai;
unionSet(x + n,fai);
return 1;
}
bool ff = 0;
for(int i = 0;i < g[x].size();i ++) {
if(g[x][i].v != fat) {
int z = g[x][i].id,zi = g[x][i].id;
if(z <= 3*n) z += n;
else z -= n;
bool fff = ff;
ff |= dfs2(g[x][i].v,x,mini,z);
if(!fff && ff) {
if(fai == 0) {
pre[zi] = x;
suf[x] = zi;
unionSet(x,zi);
}
else {
pre[zi] = fai;
suf[fai] = zi;
unionSet(fai,zi);
}
}
}
}
return ff;
}
int main() {
// freopen("tree.in","r",stdin);
// freopen("tree.out","w",stdout);
int T;
scanf("%d",&T);
while(T --) {
scanf("%d",&n);
memset(pre,0,sizeof(pre));
memset(suf,0,sizeof(suf));
memset(le,0,sizeof(le));
for(int i = 1;i < n;i ++) {
id[i] = read();
g[i].clear();
fa[i] = i;
fa[i + n] = i + n;
fa[i + 2*n] = i + n*2;
fa[i + 3*n] = i + n*3;
}
scanf("%d",&id[n]);
g[n].clear();
fa[n] = n;
fa[2*n] = 2*n;
fa[3*n] = 3*n;
fa[4*n] = 4*n;
for(int i = 1;i < n;i ++) {
s = read();o = read();
g[s].push_back(ed(o,i + n*2));
g[o].push_back(ed(s,i + n*3));
le[i + n*2] = le[i + n * 3] = 1;
}
// for(int i = 1;i <= n;i ++) printf("p:%d size:%d\n",i,g[i].size());
for(int i = 1;i <= n;i ++) {
s = id[i];
minn = 0x7f7f7f7f;
// cout<<"point:"<<i<<"("<<s<<")"<<endl;
dfs(s,0,0);
if(minn <= n) {
id[i] = minn;
dfs2(s,0,minn,0);
}
}
for(int i = 1;i <= n;i ++) {
printf("%d ",id[i]);
}putchar('\n');
}
return 0;
}

[CSP day1T3]树上的数的更多相关文章

  1. CCF CSP 201312-4 有趣的数

    CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201312-4 有趣的数 问题描述 我们把一个数称为有趣的,当且仅当: 1. 它的数字只包含0 ...

  2. 【CSP2019】树上的数

    [CSP2019]树上的数 题面 洛谷 题解 我们设每个点上的编号分别为\(a_1,a_2...a_n\). 10pts ... 菊花 假设现在菊花中心编号是\(rt\),设你依次拆边\((p_1,r ...

  3. CSP2019 树上的数 题解

    题面 这是一道典型的部分分启发正解的题. 所以我们先来看两个部分分. Part 1 菊花图 这应该是除了暴力以外最好想的一档部分分了. 如上图(节点上的数字已省略),如果我们依次删去边(2)(1)(3 ...

  4. CSP2019 D1T3 树上的数 (贪心+并查集)

    题解 因为博主退役了,所以题解咕掉了.先放个代码 CODE #include<bits/stdc++.h> using namespace std; const int MAXN = 20 ...

  5. [CSP-S2019]树上的数 题解

    CSP-S2 2019 D1T3 考场上写了2h还是爆零……思维题还是写不来啊 思路分析 最开始可以想到最简单的贪心,从小到大枚举每个数字将其移动到最小的节点.但是通过分析样例后可以发现,一个数字在移 ...

  6. [CSP-S2019] 树上的数

    考虑处理字典序的一类经典操作: 按位枚举. 我们思考一些性质: 一个点的权值出去则不会再回来. 一条边不会使用两次. 那么我们从小到大来操作. 那么存在矛盾当且仅当: 起点在之前非开始边被操作过 中间 ...

  7. 【CSP2019】题解合集

    诈个尸 先挖坑 虽然连去都没去但还是想做做 今年貌似比去年还毒瘤啊... yrx.hjw都进了省队线tql orz (myh:没AK真丢脸 Day1T1 格雷码 Day1T2 括号树 Day1T3 树 ...

  8. CSP-S 2019 Solution

    Day1-T1 格雷码(code) 格雷码是一种特殊的 \(n\) 位二进制串排列法,要求相邻的两个二进制串恰好有一位不同,环状相邻. 生成方法: \(1\) 位格雷码由两个 \(1\) 位的二进制串 ...

  9. CSP-S乱搞记

    还有一年的时间,没人能挡住我前进的脚步 以后不打算写游记了,补完这篇再写就等退役吧,不太想传播什么负能量,走这条路,希望能得到自己想要的东西 Day-n 上了一个月文化课,班主任突然催我搞竞赛??? ...

随机推荐

  1. springboot整合ueditor实现图片上传和文件上传功能

    springboot整合ueditor实现图片上传和文件上传功能 写在前面: 在阅读本篇之前,请先按照我的这篇随笔完成对ueditor的前期配置工作: springboot+layui 整合百度富文本 ...

  2. redis主从复制(九)

    先来简单了解下redis中提供的集群策略, 虽然redis有持久化功能能够保障redis服务器宕机也能恢复并且只有少量的数据损失,但是由于所有数据在一台服务器上,如果这台服务器出现硬盘故障,那就算是有 ...

  3. 使用Vite2+TypeScript4+Vue3技术栈,如何入手开发项目

    前言 今天,我们使用Vite2.0+Vue3+TS来试玩一下,开发一个demo项目.实战 我们,打开Vite官方网站(https://cn.vitejs.dev/). Vite (法语意为 " ...

  4. WPF开发随笔收录-心电图曲线绘制

    一.前言 项目中之前涉及到胎儿心率图曲线的绘制,最近项目中还需要添加心电曲线和血样曲线的绘制功能.今天就来分享一下心电曲线的绘制方式: 二.正文 1.胎儿心率曲线的绘制是通过DrawingVisual ...

  5. ConcurrentHashMap深入剖析(基于JDK1.7)

    最近有点时间,翻了翻ConcurrentHashMap的源码学习了一下,对我自己认为比较重要的一些方法进行了学习,添加了一些必要的注释,拿出来与园子的小伙伴分享一下,有说的不对的地方,还请各位批评指正 ...

  6. flex大法:一网打尽所有常见布局

    flex全称Flexible Box模型,顾名思义就是灵活的盒子,不过一般都叫弹性盒子,所有PC端及手机端现代浏览器都支持,所以不用担心它的兼容性,有了这玩意,妈妈再也不用担心我们的布局. 先简单介绍 ...

  7. linux下怎样在某个文件里面查找一个字符串?

    方法一: grep命令 举个栗子:我想要在redis.conf中查询我设置的redis密码,执行下面代码 grep "require" redis.conf #grep " ...

  8. NC16663 [NOIP2004]合并果子

    NC16663 [NOIP2004]合并果子 题目 题目描述 ​ 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. ​ 每一次合并,多多可 ...

  9. Ros的通信第一课

    //////////////////////////Ros创建发布者talker//////////////////////////////////////////////////////////// ...

  10. 【PostgreSQL 】PostgreSQL 15对distinct的优化

    示例表 table t_ex; c1 | c2 ----+---- 2 | B 4 | C 6 | A 2 | C 4 | B 6 | B 2 | A 4 | B 6 | C 2 | C 以下SQL语 ...