[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 上了一个月文化课,班主任突然催我搞竞赛??? ...
随机推荐
- vue-cli2.x配置build命令构建测试包&正式包
项目开发中常分为开发环境.测试环境.正式环境 通过vue-cli或者@vue/cli脚手架搭建的项目默认提供了开发环境和正式环境的配置.可通过js获取当前域名或其他信息来判断当前为测试环境还是正式环境 ...
- 能快速搭建三维场景,这款3D全场景编辑器你还没用过吗?
今天就给大家分享一个非常好用的老子云3D全场景编辑器,不仅可以基于GIS数据,帮助用户快速搭建3D城市大场景.实现Web端流畅展示. 并且搭建的3D场景可离线开发成一个空间信息直观的.可交互.易于设计 ...
- 使用.NetCore自带的后台作业,出入队简单模拟生产者消费者处理请求响应的数据
环境:Core:3.1的项目 说明:由于该方案为个人测试项目,重启时队列中的部分数据很可能会丢失, 对数据有要求的该方案不适用,不能照搬需要持久化处理, 另外发布到Linux Docker中通常不会自 ...
- ssh-免密钥登陆
实现openssh免密钥登陆(公私钥验证) 在主机A上,通过root用户,使用ssh-keygen生成的两个密钥:id_rsa和id_rsa.pub 私钥(id_rsa)保存在本地主机,公钥(id_r ...
- JS中通过id或者class获取文本内容
一.JS通过id获取文本内容 二.JS通过class获取文本内容
- 常用类-Instant、DateTimeFormatter类的使用
一.Instant 我们所处的时间点是在东八区,Java中Instant所计算出来的时间是按本初子午线的时间来算的,与我们的时间相差8个小时,也就是说当我的北京时间是上午九点时,本初子午线的时间是凌晨 ...
- JsonPath:针对json的强大的规则解析与参数查找工具
项目特点 GitHub项目地址:https://github.com/json-path/JsonPath 主要功能: 将Json字符串转为Java Map对象(这个不算什么,FastJson之类的工 ...
- 5-12 RabbitMQ 消息队列
RabbitMQ 什么是RabbitMQ RabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现. AMQP :Advanced Message Queue,高级消息队列协议.它是 ...
- 01-vscode自定义配色方案 插件基础上
01-下载相关主题插件 02- 点击设置按钮 复制id 03-进入插件文件 C:\Users\Administrator\.vscode\extensions 04-复制刚才的id 05-themes ...
- ajax01_基础知识
ajax请求 ajax概述 组成:asynchronous + javascript + xml 特点: 可发送异步请求(这也是与传统请求方式的区别) 用javascript语言编写代码 前后端数据交 ...