[CSP day1T3]树上的数
题面

题解
这道题由于是求字典序最小的,所以要贪心地枚举数字,然后找可以走到的编号最小的点,处理这条路径。
这条路径有一些特性。
以下是特别精炼的结论:

所以一旦选好了路径,这些边的先后顺序就被定死了,后面的路径肯定不能与他冲突
于是我们只要记录边的先后关系,然后进行非常严密的逻辑判断选择一条不冲突的路径。
复杂度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]树上的数的更多相关文章
- CCF CSP 201312-4 有趣的数
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201312-4 有趣的数 问题描述 我们把一个数称为有趣的,当且仅当: 1. 它的数字只包含0 ...
- 【CSP2019】树上的数
[CSP2019]树上的数 题面 洛谷 题解 我们设每个点上的编号分别为\(a_1,a_2...a_n\). 10pts ... 菊花 假设现在菊花中心编号是\(rt\),设你依次拆边\((p_1,r ...
- CSP2019 树上的数 题解
题面 这是一道典型的部分分启发正解的题. 所以我们先来看两个部分分. Part 1 菊花图 这应该是除了暴力以外最好想的一档部分分了. 如上图(节点上的数字已省略),如果我们依次删去边(2)(1)(3 ...
- CSP2019 D1T3 树上的数 (贪心+并查集)
题解 因为博主退役了,所以题解咕掉了.先放个代码 CODE #include<bits/stdc++.h> using namespace std; const int MAXN = 20 ...
- [CSP-S2019]树上的数 题解
CSP-S2 2019 D1T3 考场上写了2h还是爆零……思维题还是写不来啊 思路分析 最开始可以想到最简单的贪心,从小到大枚举每个数字将其移动到最小的节点.但是通过分析样例后可以发现,一个数字在移 ...
- [CSP-S2019] 树上的数
考虑处理字典序的一类经典操作: 按位枚举. 我们思考一些性质: 一个点的权值出去则不会再回来. 一条边不会使用两次. 那么我们从小到大来操作. 那么存在矛盾当且仅当: 起点在之前非开始边被操作过 中间 ...
- 【CSP2019】题解合集
诈个尸 先挖坑 虽然连去都没去但还是想做做 今年貌似比去年还毒瘤啊... yrx.hjw都进了省队线tql orz (myh:没AK真丢脸 Day1T1 格雷码 Day1T2 括号树 Day1T3 树 ...
- CSP-S 2019 Solution
Day1-T1 格雷码(code) 格雷码是一种特殊的 \(n\) 位二进制串排列法,要求相邻的两个二进制串恰好有一位不同,环状相邻. 生成方法: \(1\) 位格雷码由两个 \(1\) 位的二进制串 ...
- CSP-S乱搞记
还有一年的时间,没人能挡住我前进的脚步 以后不打算写游记了,补完这篇再写就等退役吧,不太想传播什么负能量,走这条路,希望能得到自己想要的东西 Day-n 上了一个月文化课,班主任突然催我搞竞赛??? ...
随机推荐
- 对TCP粘包拆包的理解
TCP的粘包与拆包 TCP是一种字节流(byte-stream)协议,所谓流,就是没有界限的一串数据. 一个完整的包会被TCP拆为多个包进行发送,也有可能把多个小包封装成一个大的数据包发送,这就是所谓 ...
- 使用 KubeKey 搭建 Kubernetes/KubeSphere 环境的"心路(累)历程"
目录 今天要干嘛? 在哪里干? 从哪里开始干? 快速开干! 解决依赖问题再继续干! 如何干翻重来? 连着 KubeSphere 一起干! 干不过,输了. 重整旗鼓,继续干! 再次重整旗鼓,继续干! 一 ...
- 浏览器代理user-agent
两种方法: 法1:浏览器地址栏输入:about://version,然后复制用户代理: 如果法1不行,法2肯定可以. 法2:打开任意浏览器,输入任意网址,下面以火狐和百度网址为例来进行说明: 打开火狐 ...
- docker引起服务器磁盘爆满
服务器异常 又是开开心心打开我心爱的服务器一天: 吔!这是嘛啊?我的服务器域名访问不了了,一直转圈圈超时了,好,打开ssh远程看看,吔!!!还是访问不了,宕机了?怀着一颗憋大便的心情打开了阿里云控制面 ...
- 【zigbee无线通信模块步步详解】ZigBee3.0模块建立远程网络控制方法
本文以路灯控制应用为例,简述ZigBee3.0模块使用流程. 一.建立网络 1.通过USB转串口模块将出厂的ZigBee自组网模块连接,打开上位机软件"E180-ZG120A-Setting ...
- sap 调用Http 服务
REPORT ZMJ_GETAPI. DATA: LEN TYPE I, "发送报文长度 LEN_STRING TYPE STRING, URL TYPE STRING, "接口地 ...
- SAP Drag or drop tree
1 *&---------------------------------------------------------------------* 2 *& Report RSDEM ...
- AspNetCore&云效Flow持续集成
如今有了越来越多的持续集成工具,给的个人开发者的福利也是很足了,如无必要,自建工具有时只是作为练手了. 众多持续集成工具 现在可用的持续集成工具繁多,各大云服务商都推出了持续集成,甚至是一定条件内都是 ...
- CMU15445 之 Project#0 - C++ Primer 详解
前言 这个实验主要用来测试大家对现代 C++ 的掌握程度,实验要求如下: 简单翻译一下上述要求,就是我们需要实现定义在 src/include/primer/p0_starter.h 中的三个类 Ma ...
- RPA应用场景-报税机器人
场景概述 报税机器人 所涉系统名称 税务网站 人工操作(时间/次) 53分钟 所涉人工数量 60 操作频率 每月 场景流程 1.通过RPA自动将财税信息从对应系统中导出 2.RPA根据不同的税务报表规 ...