题目背景

自选题 by ix35

题目描述

给定一张包含 \(n\) 个顶点和 \(m\) 条边的 无向连通图,Tom 和 Jerry 在图上进行了 \(q\) 次追逐游戏。

在第 \(i\) 次游戏中,Tom 一开始位于顶点 \(a_i\),而 Jerry 一开始位于顶点 \(b_i\)(双方任何时候都知道自己和对方的位置),追逐规则如下:

  • Jerry 和 Tom 交替行动,Jerry 先行动。

  • Jerry 每次行动可以通过无向图中的 任意多条边(可以选择不移动),但是在移动过程中不能经过 Tom 当前所在的结点,否则就会被抓住。

  • Tom 每次行动只能通过无向图中的 至多一条边(可以选择不移动)。

  • 如果 Tom 在一次行动后到达了 Jerry 的位置,那么 Tom 胜利。

Tom 尽量想要胜利,而 Jerry 会尽量阻止 Tom 胜利。

现在你需要对于每一局游戏,求出 Tom 是否一定能在有限次行动内获胜。

对于 \(100\%\) 的数据,\(1\leq n,m,q\leq 10^5\),\(1\leq x,y,a,b\leq n\),\(a_i\ne b_i\)。

感性一下,会发现Tom 每一步一定是走在割点上的,不然的话 Jerry 一下子就会飞走。

那么找到圆方树,那么两个点 \((x,y)\) 称为好的,当且仅当在圆方树上他们的路径中任意两点是在原图相邻的。

而 Tom 在 \(x\),Jerry 在 \(y\) 点时,如果 \(x\) 考 \(y\) 的那个连通块满足任意一个点 \(u\),\((x,u)\) 是好的,Tom 就可以抓住 Jerry.

然后可以树形 dp 求出来某一棵子树是否满足根节点到自述中其他所有节点都是好的,换根 dp 求出来是否到子树外任意一点是好的。

如果有一个点满足到另外任意一个点都是好的,那么 Tom 可以先到这个店,所有询问都是 Yes.

否则就倍增出来看 Tom 在那棵子树,然后回答答案。

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
int n,m,f[N],p[N],c,fa[N][20],dfn[N],low[N],idx,st[N],tp,dep[N],in[N],q,x,y;
vector<int>g[N],h[N];
map<int,int>mp[N];
void tarjan(int x)
{
dfn[x]=low[x]=++idx;
st[++tp]=x;
for(int v:g[x])
{
if(!dfn[v])
{
tarjan(v);
low[x]=min(low[x],low[v]) ;
if(low[v]==dfn[x])
{
++c;
while(st[tp+1]^v)
{
h[c].push_back(st[tp]),h[st[tp]].push_back(c);
--tp;
}
h[c].push_back(x),h[x].push_back(c);
}
}
else
low[x]=min(low[x],dfn[v]);
}
}
void sou(int x,int y)
{
dep[x]=dep[y]+1;
fa[x][0]=y;
for(int i=1;i<=19;i++)
fa[x][i]=fa[fa[x][i-1]][i-1];
f[x]=1;
for(int v:h[x])
{
if(v==y)
continue;
sou(v,x);
if(x<=n)
f[x]&=f[v];
else
f[x]&=mp[y][v]&f[v];
}
}
int ask(int x,int k)
{
for(int i=0;i<20;i++)
if(k>>i&1)
x=fa[x][i];
return x;
}
void dfs(int x,int y)
{
int cnt=0;
p[x]=1;
for(int v:h[x])
if(v^y)
cnt+=f[v];
for(auto v:h[x])
if(v^y&&(x<=n||in[v]==h[x].size()-1)&&cnt-f[v]==h[x].size()-1-(bool)y)
dfs(v,x);
}
int main()
{
scanf("%d%d%d",&n,&m,&q),c=n;
for(int i=1,u,v;i<=m;i++)
{
scanf("%d%d",&u,&v),mp[u][v]=mp[v][u]=1;
g[u].push_back(v),g[v].push_back(u);
}
tarjan(1);
sou(1,0);
for(int i=1;i<=n;i++)
{
for(auto v:g[i])
{
if(v>i)
continue;
if(fa[i][1]==v)
in[i]++;
else if(fa[v][1]==i)
in[v]++;
else
in[i]++,in[v]++;
}
}
dfs(1,0);
for(int i=1;i<=n;i++)
{
if(f[i]&&p[i])
{
for(int j=1;j<=q;j++)
puts("Yes");
return 0;
}
}
while(q--)
{
scanf("%d%d",&x,&y);
if(dep[y]<dep[x]||ask(y,dep[y]-dep[x])^x)
puts(p[x]? "Yes":"No");
else
puts(f[ask(y,dep[y]-dep[x]-1)]? "Yes":"No");
}
}

[2020-2021 集训队作业] Tom & Jerry的更多相关文章

  1. IOI 2020 国家集训队作业

    \(\checkmark\) 试题一 完成情况 试题二 完成情况 试题三 完成情况 cf549E cf674G arc103_f \(\checkmark\) cf594E agc034_f agc0 ...

  2. 「2020-2021 集训队作业」Yet Another Linear Algebra Problem(行列式,Binet-Cauchy 公式)

    题面 出题人:T L Y \tt TLY TLY 太阳神:Tiw_Air_OAO 「 2020 - 2021 集 训 队 作 业 」 Y e t A n o t h e r L i n e a r A ...

  3. UOJ #449. 【集训队作业2018】喂鸽子

    UOJ #449. [集训队作业2018]喂鸽子 小Z是养鸽子的人.一天,小Z给鸽子们喂玉米吃.一共有n只鸽子,小Z每秒会等概率选择一只鸽子并给他一粒玉米.一只鸽子饱了当且仅当它吃了的玉米粒数量\(≥ ...

  4. [UOJ422][集训队作业2018]小Z的礼物——轮廓线DP+min-max容斥

    题目链接: [集训队作业2018]小Z的礼物 题目要求的就是最后一个喜欢的物品的期望得到时间. 根据$min-max$容斥可以知道$E(max(S))=\sum\limits_{T\subseteq ...

  5. 【UOJ#450】【集训队作业2018】复读机(生成函数,单位根反演)

    [UOJ#450][集训队作业2018]复读机(生成函数,单位根反演) 题面 UOJ 题解 似乎是\(\mbox{Anson}\)爷的题. \(d=1\)的时候,随便怎么都行,答案就是\(k^n\). ...

  6. 【UOJ#422】【集训队作业2018】小Z的礼物(min-max容斥,轮廓线dp)

    [UOJ#422][集训队作业2018]小Z的礼物(min-max容斥,轮廓线dp) 题面 UOJ 题解 毒瘤xzy,怎么能搬这种题当做WC模拟题QwQ 一开始开错题了,根本就不会做. 后来发现是每次 ...

  7. UOJ#418. 【集训队作业2018】三角形

    #418. [集训队作业2018]三角形 和三角形没有关系 只要知道儿子放置的顺序,就可以直接模拟了 记录历史最大值 用一个pair(a,b):之后加上a个,期间最大值为增加b个 合并? A1+A2= ...

  8. 2019.2.25 模拟赛T1【集训队作业2018】小Z的礼物

    T1: [集训队作业2018]小Z的礼物 我们发现我们要求的是覆盖所有集合里的元素的期望时间. 设\(t_{i,j}\)表示第一次覆盖第i行第j列的格子的时间,我们要求的是\(max\{ALL\}\) ...

  9. 2017国家集训队作业Atcoder题目试做

    2017国家集训队作业Atcoder题目试做 虽然远没有达到这个水平,但是据说Atcoder思维难度大,代码难度小,适合我这种不会打字的选手,所以试着做一做 不知道能做几题啊 在完全自己做出来的题前面 ...

  10. 2017国家集训队作业[agc016b]Color Hats

    2017国家集训队作业[agc016b]Color Hats 题意: 有\(N\)个人,每个人有一顶帽子.帽子有不同的颜色.现在,每个人都告诉你,他看到的所有其它人的帽子共有多少种颜色,问有没有符合所 ...

随机推荐

  1. stencilJs学习之构建 Drawer 组件

    前言 在之前的学习中,我们已经掌握了 stencilJs 中的一些核心概念和基础知识,如装饰器 Prop.State.Event.Listen.Method.Component 以及生命周期方法.这些 ...

  2. prometheus 监控实战篇

    prometheus 监控 目录 prometheus 监控 1.上传tar包 2.解压到对应文件夹 3.配置开机自启动 4.配置Prometheus 5.black_exporter 监控网站状态 ...

  3. 文盘Rust——子命令提示,提高用户体验

    上次我们聊到 CLI 的领域交互模式.在领域交互模式中,可能存在多层次的子命令.在使用过程中如果全评记忆的话,命令少还好,多了真心记不住.频繁 --help 也是个很麻烦的事情.如果每次按 'tab' ...

  4. 使用Springboot+SpringCloud+Seata1.3.0+Nacos1.2.1进行全局事务管理

    一.官方文档网址 http://seata.io/zh-cn/docs/overview/what-is-seata.html Seata1.3.0开发组提供的开发文档 二.常见问题 2.1:网址: ...

  5. 7-MySQL函数

    1.分组group by 在MySQL中,GROUP BY的意思是"分组查询",它可以根据一个或多个字段对查询结果进行分组. GROUP BY的作用是通过一定的规则将一个数据集划分 ...

  6. window 安装多个低版本chrome测试

    最近在用next13做一个简单的项目,需要兼容chrome 60+以上版本,为了方便测试,特意在公司的台式机上安装了低版本. 这里简单记录下高版本覆盖低版本的问题,这个方法不影响Windows系统内已 ...

  7. Redis 不同插入方法的性能对比

    1. 测试目的 对比 Redis 不同插入方法(插入同时能设置过期时间)的性能区别. 2. 测试数据 key:SMGP_ value:JSON数据 { "spName":" ...

  8. Vue element-ui 动态生成自定义table表头实现数据渲染

    需求:1)表头的数据是动态的,有可能字段值很长且很多.解决方案自定义动态表头,字段长使用文字提示[el-tooltip组件]: 2)需要对表格data中的数据值进行枚举转成中文值,且显示不同的颜色. ...

  9. Merkle Tree 简介

    Merkle 树(Merkle Tree)是一种树状数据结构,通常用于验证大规模数据集的完整性和一致性.它的名字来源于其发明者 Ralph Merkle.Merkle 树在密码学.分布式系统和区块链等 ...

  10. PostgreSQL学习笔记-3.基础知识:CROSS、INNER、LEFT OUTER、RIGHT OUTER、FULL OUTER、UNION

    PostgreSQL JOIN 子句用于把来自两个或多个表的行结合起来,基于这些表之间的共同字段. 在 PostgreSQL 中,JOIN 有五种连接类型: CROSS JOIN :交叉连接INNER ...