
[2019 CSP-S Day1 T3]树上的数
发布日期:2021-05-07 01:00:45
浏览次数:26
分类:原创文章
本文共 3645 字,大约阅读时间需要 12 分钟。
题目
思路
假设数字 1 1 1可以移动到 1 1 1号点(即:存在合法的移动方式),那么我们就要 不惜一切代价 把 1 1 1移动过去再说。
这告诉我们,难点是判断是否存在合法的方案——不与已有的移动要求冲突。
对于每个点,其邻边的删除顺序是独立的。发现一次移动等价于:
- 对于起点,路径上的边必须第一个被删掉;
- 对于中转点,路径上的入边与出边相继被删掉;
- 对于终点,路径上的边必须最后被删掉。
然后用链表暴力判断即可。唯一不容易想到的一点,就是 过早封闭—— a a a必须第 x x x个被删掉, b b b必须倒数第 y y y个被删掉,如果 x + y ≠ d x x+y\ne d_x x+y=dx( d x d_x dx表示 x x x的度),那么也不能连接。
其他情况自己推一下就好了。也可以看代码。
代码
#include <cstdio>#include <iostream>#include <vector>using namespace std;inline int readint(){ int a = 0, f = 1; char c = getchar(); for(; c<'0' or c>'9'; c=getchar()) if(c == '-') f = -1; for(; '0'<=c and c<='9'; c=getchar()) a = (a<<3)+(a<<1)+(c^48); return a*f;}struct Edge{ int to, nxt; Edge(){ } Edge(int T,int N):to(T),nxt(N){ }};const int MaxN = 2000;int n, head[MaxN+1], cntEdge;Edge edge[MaxN<<1];int located[MaxN+1], degree[MaxN+1];void addEdge(int from,int to){ edge[cntEdge] = Edge(to,head[from]); head[from] = cntEdge ++; ++ degree[from];}void input(){ n = readint(); cntEdge = 0; for(int i=1; i<=n; ++i) head[i] = -1, degree[i] = 0; for(int i=1; i<=n; ++i) located[i] = readint(); for(int i=1,x,y; i<n; ++i){ x = readint(), y = readint(); addEdge(x,y), addEdge(y,x); }}struct Node{ Node *pre, *suf; int preLen, sufLen, id; void dispose(){ pre = suf = nullptr; // C++11对于(void*)0的新写法 preLen = sufLen = (MaxN<<2); }}node[MaxN<<1], *Head[MaxN+1], *tail[MaxN+1];bool beTail(Node *o,int pos){ // 能否成为最后一条 if(tail[pos] != nullptr) return false; if(o->suf != nullptr) return false; if(o->preLen < degree[pos]) return false; return true;}bool beHead(Node *o,int pos){ // 能否成为第一条 if(Head[pos] != nullptr) return false; if(o->pre != nullptr) return false; if(o->sufLen < degree[pos]) return false; return true;}bool linkNode(Node *a,Node *b,int pos){ if(a->suf == b) return true; if(a->suf != nullptr or b->pre != nullptr) return false; if(tail[pos] == a or Head[pos] == b) return false; if(a->preLen+b->sufLen < degree[pos]) return false; // 过早封闭 if(a->id == b->id) return false; // 已经在一条链中了 return true;}void linkNode(Node *a,Node *b){ a->suf = b, b->pre = a; for(Node *o=b; o!=nullptr; o=o->suf){ o->preLen = o->pre->preLen+1; o->id = o->pre->id; } for(Node *o=a; o!=nullptr; o=o->pre) o->sufLen = o->suf->sufLen+1;}void toBeHead(Node *o,int pos){ Head[pos] = o; o->preLen = 1; for(o=o->suf; o!=nullptr; o=o->suf) o->preLen = o->pre->preLen+1;}void toBeTail(Node *o,int pos){ tail[pos] = o; o->sufLen = 1; for(o=o->pre; o!=nullptr; o=o->pre) o->sufLen = o->suf->sufLen+1;}int answer;void dfs(int x,int pre){ pre ^= 1; if(beTail(&node[pre],x)) answer = min(answer,x); for(int i=head[x]; ~i; i=edge[i].nxt){ if(i == pre) continue; if(not linkNode(&node[pre],&node[i],x)) continue; dfs(edge[i].to,i); }}bool update(int x,int pre){ pre ^= 1; if(x == answer){ toBeTail(&node[pre],x); return true; } for(int i=head[x]; ~i; i=edge[i].nxt) if(i != pre and update(edge[i].to,i)){ linkNode(&node[pre],&node[i]); return true; } return false;}void solve(){ for(int i=0; i<cntEdge; ++i){ node[i].dispose(); node[i].id = i; } for(int i=1; i<=n; ++i) Head[i] = tail[i] = nullptr; for(int i=1,x; i<=n; ++i){ x = located[i], answer = n+1; for(int j=head[x]; ~j; j=edge[j].nxt) if(beHead(&node[j],x)) dfs(edge[j].to,j); for(int j=head[x]; ~j; j=edge[j].nxt) if(update(edge[j].to,j)){ toBeHead(&node[j],x); break; } printf("%d ",answer); } putchar('\n');}int main(){ for(int T=readint(); T; --T){ input(); solve(); } return 0;}
后记
考场时思考过“边删除的先后关系”作为判断依据。但是我是 全局性的考虑,就会导致很多问题,无法实现。
——所以 忽略无用信息(或者说 分类讨论?)很重要!我们要充分利用 每个点的邻边的删除顺序是独立的 这一 NB \text{NB} NB特征。
发表评论
最新留言
能坚持,总会有不一样的收获!
[***.219.124.196]2025年03月25日 04时38分45秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
工作动态尽在掌握 - 使用 CODING 度量团队效能
2019-03-06
CODING DevOps 代码质量实战系列最后一课,周四发车
2019-03-06
CODING DevOps 深度解析系列第二课报名倒计时!
2019-03-06
CODING DevOps 线下沙龙回顾二:SDK 测试最佳实践
2019-03-06
翻译:《实用的Python编程》03_01_Script
2019-03-06
数据结构第八节(图(下))
2019-03-06
基础篇:异步编程不会?我教你啊!CompletableFuture
2019-03-06
基于Mustache实现sql拼接
2019-03-06
气球游戏腾讯面试题滑动窗口解法
2019-03-06
POJ 2260 Error Correction 模拟 贪心 简单题
2019-03-06
POJ - 1328 Radar Installation 贪心
2019-03-06
CSUOJ Water Drinking
2019-03-06
自定义博客园博客的背景图片
2019-03-06
Spring MVC+javamail实现邮件发送
2019-03-06
Asp.NET Core 限流控制-AspNetCoreRateLimit
2019-03-06
gRPC在 ASP.NET Core 中应用学习(一)
2019-03-06
@SuppressWarnings 用法
2019-03-06
看完你就明白的锁系列之锁的状态
2019-03-06
看完这篇操作系统,和面试官扯皮就没问题了
2019-03-06
我的价值观
2019-03-06