题解:P7353 [2020-2021 集训队作业] Tom Jerry

news/2024/10/10 10:21:08/文章来源:https://www.cnblogs.com/louisliang/p/18455774

Problem Link

思考 Tom 怎么获胜,有以下两种情况:

  1. Tom 不断限制 Jerry 的活动范围,直到困死。
  2. ~Tom 瞎走都可以赢~,有一个点能让 Tom 必胜。

对于(1),显然 Tom 需要不断走割点,由此想到圆方树。

这里有个圆方树

假设 Tom 在 \(a\),Jerry 在 \(d\),Jerry 能在 \(a\) 的子树里任意走,所以 Tom 需要让 \(a\) 能直接到达 \(b\)\(c\),否则就输了。由此看出每当 Tom 在 \(x\),Jerry 在 \(x\) 的子树 \(y\) 内时,\(x\) 必须直接到达 \(y\) 代表的点双连通分量中的任意点。此时 Tom 必胜。

对于(2),考虑能让 Tom 必胜的那个点 \(x\),此时 Jerry 可以在任何地方(否则(1)就讨论过了)。Tom 必胜条件就是对于 \(x\) 的任何子树,(1)的条件都成立。

若(1)(2)都不成立,Tom 必败。

接下来实现挺复杂的,我看其他 dalao 题解是没怎么看懂(我太蒻了),这里介绍一下我的写法。

考虑如何表示 \(x\) 能直接到达其点双连通分量的任意点。可以将这个状态放到 \(x\) 到对应方点的边上。

枚举原图上的边,如 \((a,b)\),则在圆方树上让 \(w(a,A)\)\(w(b,A)\) 各加一,这很好实现。\(a\) 能直接到 \(A\) 中任意点的充要条件是 \(w(a,A) = sz_A-1\)\(sz_A\)\(A\) 代表的点双连通分量的大小)。

必胜条件可以转化为:对于一个根为 \(x\) 的子树中,所有 \(u\) 是圆点,\(v\) 是方点,\(dep_u<dep_v\) 的边 \((u,v)\) (如下图红边)均合法。记不合法的边的数量\(f_x\),满足条件且不合法的的边称为不合法边。

容易得到转移:\(f_{y \in son_x} \rightarrow f_x\)。对于不合法边 \((u,v)\),为代码更好写,让 \(f_v \leftarrow f_v+1\)

考虑换根 dp,记 \(g_x\) 为删去 \(x\) 的子树(除了 \(x\))剩下的子树中不合法边的数量

转移为:\(g_y=g_x+f_x-f_y+\Delta\)

\(\Delta\) 的取值有:

  • \((x,y)\) 有原来是不合法边,\(\Delta=-1\)
  • \((x,y)\) 现在是不合法边,\(\Delta=1\)
  • \((x,y)\) 啥都不是,\(\Delta=0\)

最后用 lca 求出需要满足的子树 \(x\),注意特判情况(2)。

默认 \(n,m,q\) 同级,时间复杂度为 \(O(n\log n)\)

update on 2024.10.3 修改代码中的部分错误

Code:

#include<iostream>
#include<cstdlib>
#include<ctime>
#include<cassert>
#include<vector>
#include<cmath>
#include<cstring>
#include<set>
#include<queue>
#include<algorithm>
using namespace std;
const int N = 2e5 + 10, M = 2 * N;
int dfn[N], low[N], st[N], sz[N], f[N], g[N], tot;
int fa[N][21], dep[N], n, m, q, ifa[N];
vector <int> e[N];
int head[N], vi[M], ne[M], wi[M], htot;
vector < pair <int, int> > vt;
void addedge(int u, int v){ne[++htot] = head[u], vi[htot] = v, head[u] = htot;
}
void add(int u, int v){addedge(u, v);addedge(v, u);
}
void tarjin(int x){dfn[x] = low[x] = ++dfn[0], st[++st[0]] = x;for(int y : e[x]){if(!dfn[y]){tarjin(y);low[x] = min(low[x], low[y]);if(low[y] == dfn[x]){add(x, ++tot);sz[tot] = 2;while(st[st[0]] != y){sz[tot]++;add(st[st[0]--], tot);}add(st[st[0]--], tot);}}elselow[x] = min(low[x], dfn[y]);}
}
void ad(int u, int v){while(u != v){if(dep[u] < dep[v])swap(u, v);wi[ifa[u]]++, u = fa[u][0];}
}
void dfs1(int x, int pfa){dep[x] = dep[pfa] + 1, fa[x][0] = pfa;for(int i = 1; i <= 20; i++)fa[x][i] = fa[fa[x][i - 1]][i - 1];for(int i = head[x]; i; i = ne[i]){int y = vi[i];if(y == pfa)continue;ifa[y] = i;dfs1(y, x);}
}
void dfs2(int x, int pfa, int op){f[x] = op;for(int i = head[x]; i; i = ne[i]){int y = vi[i];if(y == pfa)continue;dfs2(y, x, (x <= n && wi[i] != sz[y] - 1));f[x] += f[y];}
}
void dfs3(int x, int pfa){for(int i = head[x]; i; i = ne[i]){int y = vi[i];if(y == pfa)continue;int t = g[x] + f[x] - f[y];if(y <= n && wi[i] != sz[x] - 1)t++;if(x <= n && wi[i] != sz[y] - 1)t--;g[y] = t;dfs3(y, x);}
}
int lca(int x, int y){if(dep[x] < dep[y])swap(x, y);for(int i = 20; ~i; i--)if(dep[fa[x][i]] >= dep[y])x = fa[x][i];if(x == y)return x;for(int i = 20; ~i; i--)if(fa[x][i] != fa[y][i])x = fa[x][i], y = fa[y][i];return fa[x][0];
}
bool check(int x, int y){if(lca(x, y) == x){int z = y;for(int i = 20; ~i; i--)if(dep[fa[z][i]] > dep[x])z = fa[z][i];return f[z] == 0;}return g[x] == 0;
}
int main(){ios::sync_with_stdio(false);cin.tie(nullptr);cin >> n >> m >> q;for(int i = 1, u, v; i <= m; i++){cin >> u >> v;vt.push_back(make_pair(u, v));e[u].push_back(v);e[v].push_back(u);}tot = n;tarjin(1);dfs1(1, 0);for(auto i : vt)ad(i.first, i.second);dfs2(1, 0, 0);dfs3(1, 0);bool flag = 0;for(int i = 1; i <= n; i++)flag |= (f[i] + g[i] == 0);while(q--){int a, b;cin >> a >> b;if(flag){cout << "Yes\n";continue;}cout << (check(a, b)? "Yes\n" : "No\n");}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/810951.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

利用大模型设计测试用例

安装python 依赖 pip install torch transformers accelerate sentencepiece python代码,设计一个测试用例from transformers import AutoTokenizer, AutoModelForCausalLM import os import torch # 导入 torch 库# 设置 HTTP 和 HTTPS 代理(如果需要) os.environ[http_pr…

测试流程必须严格执行吗?

技术交流群有同学问了这样一个问题:公司有较为严格的测试流程和项目交付规范,但目前工期紧张且资源严重不足,是否还需要严格遵守流程规范。如果严格遵守流程规范则可能要延期交付,或者项目组的同学需要大量加班,有什么解决办法?该说不说,这确实是很头疼的问题。对项目管…

Semaphore源码简单解读

Semaphore源码解读 注意,阅读本文需要了解AQS,AQS采用了模板设计模式。后续本人会完善这篇文章 Semaphore的方法acquire() 阻塞获得一个许可,会阻塞,直到得到一个可用许可或被中断 重载版本 acquire(n) :尝试获取n个许可 acquireUninterruptibly() 类acquire,但不可中断 …

捕鱼船识别检测预警系统

捕鱼船识别检测预警系统通过图像识别和数据分析技术,捕鱼船识别检测预警系统实时监测水域中的捕鱼船活动,系统利用河道两岸的摄像头,对捕鱼船的外形、大小、航行轨迹等进行检测和识别。捕鱼船识别检测预警系统一旦系统识别到违规捕捞行为,立即发出预警信号,并通知相关部门…

加油站抽烟烟火智能识别系统

加油站抽烟烟火智能识别系统利用摄像头和智能分析技术,加油站抽烟烟火智能识别系统实时监测加油站内的加油人员行为,加油站抽烟烟火智能识别系统通过图像识别和行为分析,识别出抽烟和燃放烟火的情况,并发出预警信号以提醒相关人员。加油站抽烟烟火智能识别系统能够实时监测…

希音面试:Redis脑裂,如何预防?你能解决吗?(看这篇就够了)

文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录 博客园版 为您奉上珍贵的学习资源 : 免费赠送 :《尼恩Java面试宝典》 持续更新+ 史上最全 + 面试必备 2000页+ 面试必备 + 大厂必备 +涨薪必备 免费赠送 :《尼恩技术圣经+高并发系列PDF》 ,帮你 实现技术自由,…

稀疏促进动态模态分解(SPDMD)详细介绍以及应用

在数据驱动分析领域,从复杂流体流动中提取有意义的模式一直是一个重大挑战。稀疏促进动态模态分解(Sparsity Promoting Dynamic Mode Decomposition, SPDMD)提供了一种有效方法,能够揭示最主要的特征,同时去除冗余信息,从而实现更高效和更具洞察力的分解。这种方法将动态…

CSP2024 前集训:多校A层冲刺NOIP2024模拟赛04

前言T1 签了。 T2 一眼后缀数组板子,但是复杂度是 \(O(nq\log(n))\) 的,极限数据本地 \(4\) 秒,但如果您会 \(O(n)\) 求后缀数组的话就直接过掉了,但赛时数据貌似纯随机,遂可以直接过掉,可以优化成 \(O(n^2\log(n)+nq)\) 或 \(O(n^2\log(n)+q)\) 的,赛时想打这个但是怕常…

抽象函数中图象变换的应用

一 问题引入 在高一学函数性质时,我们会遇到一些抽象函数的问题,先看两道例题: 【例1】已知函数\(f\left(2x+1\right)\)的定义域为\(\left[1,2\right]\),则函数\(f\left(4x+1\right)\)的定义域是 . 【例2】已知函数\(f\left(x\right)\)的定义域为\(\mathrm{R}\)…

P7394 「TOCO Round 1」History

操作树加二分,目前题解区没有这种做法。 发现操作一可逆,可以用操作树,操作三解决。 操作一单点修改没什么好说的。 接下来看操作二。令 \(fa_{x,k}\) 为 \(x\) 的 \(k\) 级祖先。 发现对于每个询问中,如果 \(y\) 为奇数那么答案为 \(0\)。如果 \(y\) 为偶数,那么答案就是…

php网站忘记后台密码忘记怎么办

如果你忘记了PHP网站后台的登录密码,可以通过以下几种方法来尝试恢复或重置密码:检查邮箱:如果在创建账户时设置了找回密码的功能,并且绑定了邮箱,可以先检查注册时使用的邮箱是否有找回密码的邮件。数据库直接修改:通过phpMyAdmin或其他数据库管理工具登录到MySQL数据库…

公司网站新闻图片修改方式

要修改公司网站上的新闻图片,通常可以按照以下步骤操作:备份原图:在进行任何修改之前,确保先备份原始图片文件,以防修改后不满意或出现其他问题。选择工具:根据需要修改的内容选择合适的图像编辑工具。常见的工具有Photoshop、GIMP(免费开源软件)或者在线编辑器如Canva…