题目描述

C 国是一个繁荣昌盛的国家,它由 \(n\) 座城市和 \(m\) 条有向道路组成,城市从 \(1\) 到 \(n\) 编号。如果从 \(x\) 号城市出发,经过若干条道路后能到达 \(y\) 号城市,那么我们称 \(x\) 号城市可到达 \(y\) 号城市,记作 \(x\Rightarrow y\)。C 国的道路有一个特点:对于三座城市 \(x\),\(y\),\(z\),若 \(x\Rightarrow z\) 且 \(y\Rightarrow z\),那么有 \(x\Rightarrow y\) 或 \(y\Rightarrow x\)。

再过一个月就是 C 国成立的千年纪念日,所以 C 国的人民正在筹备盛大的游行庆典。目前 C 国得知接下来会有 \(q\) 次游行计划,第 \(i\) 次游行希望从城市 \(s_i\) 出发,经过若干个城市后,在城市 \(t_i\) 结束,且在游行过程中,一个城市可以被经过多次。为了增加游行的乐趣,每次游行还会临时修建出 \(k\)(\(0 \le k \le 2\))条有向道路专门供本次游行使用,即其它游行计划不能通过本次游行修建的道路。

现在 C 国想知道,每次游行计划可能会经过多少座城市

注意:临时修建出的道路可以不满足 C 国道路原有的特点

先缩点,反正不影响可达性。

在那个性质中,\(x\Rightarrow z\) 且 \(y\Rightarrow z\),那么 \(x\) 和 \(y\) 中有一个可达另一个,设 \(x\Rightarrow y\),那么此时如果 \(x\) 到 \(z\) 有边,我们可以删去 \(x\) 到 \(z\) 的边。

换言说,对于一个点的所有入边,我们只保留拓扑序最大的那条边(拓扑序应该是固定的),不影响可达性。所以现在变成了一棵树的问题。要在树上增加几条边后,判断有几个点既能被 \(s\) 到达又能到达 \(t\)。

当 \(k=0\) 和 \(k=1\) 时写个分讨就行了,但是 \(k=2\) 不该有人想写分讨吧。此时可以把 \(s\),\(t\) 和其他边的端点放在一起建出虚树,然后此时只有 \(O(k)\) 条边,用 bfs 求出可达性之后就好做了。

#include<bits/stdc++.h>
using namespace std;
const int N=6e5+5;
int n,m,q,k,tme,dfn[N],low[N],id[N],st[N],tp,idx,hd[N],e_num,u[N],v[N],rt,fa[N][23],dep[N],dp[N],s,t,ans,l=1,r,vs[2][N],sz[N],p[N];
struct edge{
int v,nxt,f,w;
}e[N];
void add_edge(int u,int v,int f=0,int w=0)
{
e[++e_num]=(edge){v,hd[u],f,w};
hd[u]=e_num;
}
int read()
{
int s=0;
char ch=getchar();
while(ch<'0'||ch>'9')
ch=getchar();
while(ch>='0'&&ch<='9')
s=s*10+ch-48,ch=getchar();
return s;
}
void topo()
{
idx=0;
for(int i=1;i<=tme;i++)
if(!dfn[i])
st[++r]=i;
rt=st[1];
while(l<=r)
{
for(int i=hd[st[l]];i;i=e[i].nxt)
{
--dfn[e[i].v];
if(!dfn[e[i].v])
fa[e[i].v][0]=st[l],st[++r]=e[i].v;
}
++l;
}
}
void tarjan(int x)
{
dfn[x]=low[x]=++idx,st[++tp]=x;
for(int i=hd[x];i;i=e[i].nxt)
{
if(!dfn[e[i].v])
tarjan(e[i].v),low[x]=min(low[x],low[e[i].v]);
else if(!id[e[i].v])
low[x]=min(low[x],dfn[e[i].v]);
}
if(dfn[x]==low[x])
{
++tme;
while(st[tp]^x)
sz[id[st[tp--]]=tme]++;
sz[id[st[tp--]]=tme]++;
}
}
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];
}
void dfs(int x)
{
dep[x]=dep[fa[x][0]]+1;
dp[x]=dp[fa[x][0]]+sz[x];
dfn[x]=++idx;
for(int i=1;i<=20;i++)
fa[x][i]=fa[fa[x][i-1]][i-1];
for(int i=hd[x];i;i=e[i].nxt)
dfs(e[i].v);
}
int cmp(int x,int y)
{
return dfn[x]<dfn[y];
}
void clr(int x)
{
hd[x]=vs[0][x]=vs[1][x]=0;
}
void sou(int x)
{
if(vs[0][x]&&vs[1][x])
ans+=sz[x];
for(int i=hd[x];i;i=e[i].nxt)
{
if(!e[i].f&&!e[i].w)
{
sou(e[i].v);
if(vs[0][x]&&vs[1][e[i].v])
ans+=dp[fa[e[i].v][0]]-dp[x];
}
}
}
void bfs(int x,int op)
{
low[l=r=1]=x;
vs[op][x]=1;
while(l<=r)
{
for(int i=hd[low[l]];i;i=e[i].nxt)
{
if(!vs[op][e[i].v]&&e[i].w==op)
{
vs[op][e[i].v]=1;
low[++r]=e[i].v;
}
}
++l;
}
}
void addedge(int u,int v,int f=0)
{
//printf("hjhyyds:%d %d\n",u,v);
//printf("qzm:%d %d\n",u,v);
add_edge(u,v,f,0);
add_edge(v,u,f,1);
}
int main()
{
n=read(),m=read(),q=read(),k=read();
for(int i=1;i<=m;i++)
u[i]=read(),v[i]=read(),add_edge(u[i],v[i]);
for(int i=1;i<=n;i++)
if(!dfn[i])
tarjan(i);
memset(hd,e_num=0,sizeof(hd));
memset(dfn,0,sizeof(dfn));
for(int i=1;i<=m;i++)
if(id[u[i]]^id[v[i]])
add_edge(id[u[i]],id[v[i]]),++dfn[id[v[i]]];
topo();
memset(hd,e_num=idx=0,sizeof(hd));
for(int i=1;i<=tme;i++)
if(i^rt)
add_edge(fa[i][0],i);
dfs(rt);
while(q--)
{
int rt;
scanf("%d%d",&s,&t),m=e_num=ans=0;
p[++m]=id[s],p[++m]=id[t];
//printf("%d %d\n",id[s],id[t]);
for(int i=1;i<=k;i++)
{
scanf("%d%d",u+i,v+i);
p[++m]=id[u[i]],p[++m]=id[v[i]];
//printf("%d %d\n",id[u[i]],id[v[i]]);
}
sort(p+1,p+m+1,cmp);
m=unique(p+1,p+m+1)-p-1;
for(int i=1;i<=m;i++)
clr(p[i]);
clr(rt=st[tp=1]=lca(p[1],p[m]));
for(int i=2;i<=m;i++)
clr(lca(p[i-1],p[i]));
for(int i=1;i<=m;i++)
{
if(p[i]==st[1])
continue;
int d=lca(p[i],st[tp]);
if(d^st[tp])
{
while(dfn[d]<dfn[st[tp-1]])
addedge(st[tp-1],st[tp]),--tp;
if(d^st[tp-1])
addedge(d,st[tp]),st[tp]=d;
else
addedge(d,st[tp--]);
}
st[++tp]=p[i];
}
for(int i=1;i<tp;i++)
addedge(st[i],st[i+1]);
for(int i=1;i<=k;i++)
if(id[u[i]]^id[v[i]])
addedge(id[u[i]],id[v[i]],1);
bfs(id[s],0);
bfs(id[t],1);
sou(rt);
printf("%d\n",ans);
}
}

[NOI2021] 庆典的更多相关文章

  1. bzoj 1825: [JSOI2010]蔬菜庆典

    1825: [JSOI2010]蔬菜庆典 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 112  Solved: 45[Submit][Status][ ...

  2. i春秋四周年庆典狂欢丨价值6000元的Web安全课程免费送啦

    重磅好消息 i春秋四周年庆典狂欢 感恩回馈新老用户 5888元的Web安全线上提高班 988元的Web安全线上入门班 免费送啦 快来围观 活动详情 1.活动时间:6月17日—6月30日 2.活动规则: ...

  3. 【LOJ】#3103. 「JSOI2019」节日庆典

    LOJ#3103. 「JSOI2019」节日庆典 能当最小位置的值一定是一个最小后缀,而有用的最小后缀不超过\(\log n\)个 为什么不超过\(\log n\)个,看了一下zsy的博客.. 假如\ ...

  4. [JSOI2019]节日庆典 做题心得

    [JSOI2019]节日庆典 做题心得 一个性质有趣的字符串题 这要是在考场上我肯定做不出来吧 一开始还以为要 SAM 什么的暴力搞,没想到只用到了 \(Z\) 函数 -- 也是我生疏了罢 (学了啥忘 ...

  5. NOI2021游记

    NOI2021游记 前言 写于 2021.7.28,成绩榜刚出后几个小时.总分 345 拿到银牌 183 名. 我的高中 OI 生活在这里画上句号.结局对我而言虽然不够完美,但是无论怎样都是我人生道路 ...

  6. NOI2021 去不了记

    没错,由于某些 zszz 的原因,我是真的去不了了(指去不了 ZJ) Day -11 ~ -7 - 2021.7.12 - 2021.7.16 令人自闭的 ISIJ 终于结束了----From ycx ...

  7. [NOI2021] 量子通信

    嗯. NOI2021最白给的一题. PS:很后悔没打同步赛,少了一张同步赛Ag 考虑加黑的256位01串,我们思考一下. 因为\(k\)小于16,所以我们直接分成16块.所以一定可以的绝对有一块是完全 ...

  8. NOI2021 同步赛游记

    写在前面的话 为什么叫游记呢?因为我第一天是在划水中度过的,错过了对原题的发现. O n e I n D a r k \tt OneInDark OneInDark 无比风光地去了浙江,却倒霉地遇上了 ...

  9. Windows10一周年庆典壁纸

    example: 下载:http://pan.baidu.com/s/1b55D5k

  10. bzoj1825: [JSOI2010]蔬菜庆典

    Description Input Output 对于每组数据,输出一行.若蔬菜的总价能无限制增大,输出"+inf"(不含引号).否则输出一个整数,表示所有蔬菜的最大总价.   首 ...

随机推荐

  1. ViTPose+:迈向通用身体姿态估计的视觉Transformer基础模型

    身体姿态估计旨在识别出给定图像中人或者动物实例身体的关键点,除了典型的身体骨骼关键点,还可以包括手.脚.脸部等关键点,是计算机视觉领域的基本任务之一.目前,视觉transformer已经在识别.检测. ...

  2. Tcp/Ip协议 A类B类C类D类 地址

    TCP(传输控制协议):负责和远程主机连接  Ip(网际协议):负责寻址,使报文发送到其该在的地方 Ip地址:是TCP/IP的网络层用以标识网络中主机的逻辑地址,可以唯一标识Interent中的一台主 ...

  3. 【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅

    前言 缘由 博友的需求就是我最大的动力 博友一说话,本狗笑哈哈.博友要我写啥,我就写啥. 特来一篇关于SpringBoot接口返回结果及异常统一处理,虽说封不封装都能用,但咱后端也得给前端小姐姐留个好 ...

  4. MySQL 表分区简介

    MySQL表分区是一种数据库管理技术,用于将大型表拆分成更小.更可管理的分区(子表).每个分区可以独立进行维护.备份和查询,从而提高数据库性能和管理效率.以下是详细介绍MySQL表分区的步骤和注意事项 ...

  5. ios ipa apple company 开发者账号申请分享攻略

    ios公司开发者账号申请分享攻略 好不容易终于申请下来了ios 公司开发者账号,真是一路艰辛和漫长啊,特别是对于远在大洋彼岸的大中华国家.以下我就分享一下这一路下来的经验,希望对于那些新手同仁们有所帮 ...

  6. 初探富文本之React实时预览

    初探富文本之React实时预览 在前文中我们探讨了很多关于富文本引擎和协同的能力,在本文中我们更偏向具体的应用组件实现.在一些场景中比如组件库的文档编写时,我们希望能够有实时预览的能力,也就是用户可以 ...

  7. 【第一章 web入门】afr_3——模板注入与proc文件夹

    [第一章 web入门]afr_3--模板注入与proc文件夹 题目来源n1book,buu上的环境 看题 url中提供了name参数,类似在路径中进行了文件名查询然后展示: 随便输入一个数字: 说明肯 ...

  8. 一个Node.js的小爬虫

    爬虫其实就是对网页内特定id.class.标签内容的提取,多是循环出来的,对我们爬取非常便利. 1.安装node node官网下载安装包安装,后在命令行工具中输入node -v查看node安装的版本. ...

  9. Golang 面向对象深入理解

    1 封装 Java 中封装是基于类(Class),Golang 中封装是基于结构体(struct) Golang 的开发中经常直接将成员变量设置为大写使用,当然这样使用并不符合面向对象封装的思想. G ...

  10. JavaScript用策略模式消除if else 和 switch

    js程序中最常用的if else循环,如果分枝很多的的情况下难免使写出的程序又臭又长,但是根据需求又必须将这些分支处理,此时稍有经验的程序员可能会想到用switch case优化但是只是仅仅做到利于阅 ...