题目传送门(内部题55)


输入格式

第一行,包含两个整数:$n,m,q$,表示敌军城市数、路数和情报数。
接下来$m$行,每行包含两个整数:$u,v$,表示从$u$到$v$包含一条单向道路。
接下来$q$行,每行包含一些整数:$k\ u_1\ u_2...u_k$,表示敌军会向$u_1...u_k$这$k$个城市派遣大军。


输出格式

对于每个询问,输出一行包含一个整数表示必经的城市数。


样例

样例输入1:

4 3 2
1 2
2 3
2 4
2 3 4
2 2 4

样例输出1:

2
2

样例输入2:

4 4 1
1 2
1 3
2 4
3 4
1 4

样例输出2:


数据范围与提示

样例$1$解释:

两个询问的必经点为:$1,2$

样例$2$解释:

询问的必经点为:$1,4$

数据范围:

对于$10\%$的数据,$1\leqslant n\leqslant 7,1\leqslant m\leqslant 10,1\leqslant q\leqslant 100$;
对于$40\%$的数据,$1\leqslant n\leqslant 50,000,m=n-1,1\leqslant q\leqslant 100,000$;
对于$100\%$的数据,$1\leqslant n\leqslant 50,000,1\leqslant m\leqslant 100,000,1\leqslant q\leqslant 100,000,\sum k\leqslant 100,000$。


题解

首先,想吐槽一下出题人,下面是官方题解中的第一句话:

可能是因为我的语文真的不好,反正我是没看出来是$DAG$,然而就因为这个打乱了我整场考试的节奏。

两种解法,我们一一道来:

$1.$支配树:

支配树板子题,简单讲一下

对于$40\%$的数据,是一棵树,我们无非就是求出$k$个数的$lca$,然后$depth[lca]$就是答案。

那么我们现在考虑不是一棵树的情况,就像样例$2$,会是类似下面的一张图:

对于点$6$,从$1$到它的必经点就是$1,2,5,6$,那么我们考虑如何求出这个答案。

对于$DAG$,我们就考虑$topsort$。

还是考虑利用树的情况的$depth[lca]$,那么我们就是想办法将$5$的直接父亲设为$2$即可。

思考一下下面的操作:

  $\alpha.$如果一个点第一次被访问,那么就现将它的父亲设为指向它的点;如上图中,相当于$3\sim 5$和$4\sim 5$都没有被经过过,现在我们走了$3\sim 5$这条边,然后我们先将$5$的直接父亲设为$3$。

  $\beta.$如果这个点已经被访问过了,那么我们将它的直接父亲设为现在指向它的这个点和现在所记录的这个点的直接父亲的$lca$;如上图中,相当于我们已经经过了$3\sim 5$这条边,然而还没有经过过$4\sim 5$这条边,现在我们走了$4\sim 5$这条边,然后我们要将$5$这个点的直接父亲设置为$3$和$4$的$lca$,即为$2$号点。

而对于上面这张图,你可以将其理解为我们将其变为了下图:

重复上面的操作,直到完成整个$topsort$,我们也就相当于将其变成了一棵树,也就转化成了$40\$数据的解法。

时间复杂度:$\Theta(k\log n)$。

期望得分:$100$分。

实际得分:$100$分。

$2.bitset$:

这个就很简单了,无非就是利用$bitset$记录一下必须经过的点,还是分为两种情况:

  $\alpha.$还没有被访问过,直接将指向它的点的$bitset$传给它,不要忘了它自己。

  $\beta.$被访问过,那么将它的$bitset$与指向它的$bitset$取$\&$即可。

注意空间问题,需要将$bitset$开一半,然后先处理编号前$25000$的点,然后再处理编号后$25000$号点,否则空间会超;答案就是两次处理出来的$.count()$的和。

时间复杂度:$\Theta(\frac{k\times n}{32})$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

支配树:

#include<bits/stdc++.h>
using namespace std;
struct rec{int nxt,to;}e[100001];
int head[50001],cnt;
int n,m,q,k;
int du[50001];
int depth[50001],fa[50001][21];
int que[50001];
void add(int x,int y)
{
e[++cnt].nxt=head[x];
e[cnt].to=y;
head[x]=cnt;
}
int LCA(int x,int y)
{
if(depth[x]<depth[y])swap(x,y);
for(int i=20;i>=0;i--)
if(depth[fa[x][i]]>=depth[y])x=fa[x][i];
if(x==y)return x;
for(int i=20;i>=0;i--)
if(fa[x][i]!=fa[y][i])
{
x=fa[x][i];
y=fa[y][i];
}
return fa[x][0];
}
void topsort()
{
que[1]=depth[1]=1;
int h=0,t=1;
while(h<=t)
{
h++;
depth[que[h]]=depth[fa[que[h]][0]]+1;
for(int i=1;i<=20;i++)
fa[que[h]][i]=fa[fa[que[h]][i-1]][i-1];
for(int i=head[que[h]];i;i=e[i].nxt)
{
if(!fa[e[i].to][0])fa[e[i].to][0]=que[h];
else fa[e[i].to][0]=LCA(fa[e[i].to][0],que[h]);
du[e[i].to]--;
if(!du[e[i].to])que[++t]=e[i].to;
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);du[y]++;
}
topsort();
while(q--)
{
int lca;
scanf("%d%d",&k,&lca);
k--;while(k--)
{
int x;
scanf("%d",&x);
lca=LCA(lca,x);
}
printf("%d\n",depth[lca]);
}
return 0;
}

$bitset$:

#include<bits/stdc++.h>
using namespace std;
struct rec{int nxt,to;}e[100001];
int head[50001],cnt;
int n,m,q;
int du[2][50001];
int que[50001];
int k[100001];
int ans[100001];
bool vis[50001];
vector<int> question[100001];
bitset<25000> bit[50001],flag;
void add(int x,int y)
{
e[++cnt].nxt=head[x];
e[cnt].to=y;
head[x]=cnt;
}
void topsort1()
{
que[1]=1;
int h=0,t=1;
while(h<=t)
{
h++;
if(que[h]<=25000)bit[que[h]][que[h]]=1;
for(int i=head[que[h]];i;i=e[i].nxt)
{
if(vis[e[i].to])bit[e[i].to]&=bit[que[h]];
else
{
bit[e[i].to]=bit[que[h]];
vis[e[i].to]=1;
}
du[0][e[i].to]--;
if(!du[0][e[i].to])
que[++t]=e[i].to;
}
}
}
void topsort2()
{
que[1]=1;
int h=0,t=1;
while(h<=t)
{
h++;
if(que[h]>25000)bit[que[h]][que[h]-25000]=1;
for(int i=head[que[h]];i;i=e[i].nxt)
{
if(vis[e[i].to])bit[e[i].to]&=bit[que[h]];
else
{
bit[e[i].to]=bit[que[h]];
vis[e[i].to]=1;
}
du[1][e[i].to]--;
if(!du[1][e[i].to])
que[++t]=e[i].to;
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
du[0][y]++;
du[1][y]++;
}
topsort1();
for(int i=1;i<=q;i++)
{
int x;scanf("%d%d",&k[i],&x);
question[i].push_back(x);
flag=bit[x];
for(int j=2;j<=k[i];j++)
{
scanf("%d",&x);
flag&=bit[x];
question[i].push_back(x);
}
ans[i]=flag.count();
}
for(int i=1;i<=50000;i++)bit[i]&=0;
memset(vis,0,sizeof(vis));
topsort2();
for(int i=1;i<=q;i++)
{
flag=bit[question[i][0]];
for(int j=1;j<k[i];j++)
flag&=bit[question[i][j]];
printf("%d\n",ans[i]+flag.count());
}
return 0;
}

rp++

[CSP-S模拟测试]:attack(支配树+LCA+bitset)的更多相关文章

  1. 2018.06.27 NOIP模拟 节目(支配树+可持久化线段树)

    题目背景 SOURCE:NOIP2015-GDZSJNZX(难) 题目描述 学校一年一度的学生艺术节开始啦!在这次的艺术节上总共有 N 个节目,并且总共也有 N 个舞台供大家表演.其中第 i 个节目的 ...

  2. [07/18NOIP模拟测试5]超级树

    鬼能想到的dp定义:dp[i][j]表示在一棵i级超级树中,有j条路径同时存在且这j条路径没有公共点时,可能的情况数 刚开始我也没看懂,所以举个例子 如一个2级的超级树,父节点为1,左右儿子为2,3 ...

  3. [CSP-S模拟测试]:Walk(树的直径+数学)

    题目描述 给定一棵$n$个节点的树,每条边的长度为$1$,同时有一个权值$w$.定义一条路径的权值为路径上所有边的权值的最大公约数.现在对于任意$i\in [1,n]$,求树上所有长度为$i$的简单路 ...

  4. [CSP-S模拟测试]:柱状图(树状数组+二分+三分)

    题目描述 $WTH$获得了一个柱状图,这个柱状图一共有$N$个柱子,最开始第$i$根柱子的高度为$x_i$,他现在要将这个柱状图排成一个屋顶的形状,屋顶的定义如下:$1.$屋顶存在一个最高的柱子,假设 ...

  5. [CSP-S模拟测试]:count(树分块)

    题目描述 李华终于逃离了无尽的英语作文,重获自由的他对一棵树产生了兴趣.首先,他想知道一棵树是否能分成大小相同的几块(即切掉一些边,使得每个连通块的点数相同).然后,他觉得这个问题过于简单,于是他想知 ...

  6. [CSP-S模拟测试]:影魔(树状数组+线段树合并)

    题目背景 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵魂,都有着自己 ...

  7. [7.18NOIP模拟测试5]砍树 题解(数论分块)

    题面(加密) 又考没学的姿势……不带这么玩的…… 考场上打了个模拟 骗到30分滚粗了 稍加思考(滑稽)可将题面转化为: 求一个最大的$d$,使得 $\sum \limits _{i=1}^n {(\l ...

  8. [CSP-S模拟测试]:统计(树状数组+乱搞)

    题目传送门(内部题120) 输入格式 第一行,两个正整数$n,m$. 第二行,$n$个正整数$a_1,a_2,...,a_n$,保证$1\leqslant a_i\leqslant n$,可能存在相同 ...

  9. [CSP-S模拟测试51]题解

    错失人生中第一次AK的机会…… A.attack 支配树板子题.考场上发明成功√ 首先支配树上两点路径之间的点都是必经之点,根据这个性质我们就可以yy出建树的方法.跑拓扑,在每个点(设为$x$)即将入 ...

随机推荐

  1. Python算法每日一题--002--求众数

    给定一个大小为 n 的数组,找到其中的众数.众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素. 你可以假设数组是非空的,并且给定的数组总是存在众数. 示例 1: 输入: [3,2,3]输出: 3示 ...

  2. 【ABAP系列】SAP ABAP与Java数据类型的对应关系

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP与Java数据类 ...

  3. 校内模拟赛 : Rima —— 字典树+树形DP

    首先说一下,对一个刚学Trie树的蒟蒻来说(就是我),这道题是一道好题.Trie树比较简单,所以就不详细写了. Rima 内存限制:256 MiB 时间限制:1000 ms 标准输入输出 题目类型:传 ...

  4. < 利用Python进行数据分析 - 第2版 > 第五章 pandas入门 读书笔记

    <利用Python进行数据分析·第2版>第五章 pandas入门--基础对象.操作.规则 python引用.浅拷贝.深拷贝 / 视图.副本 视图=引用 副本=浅拷贝/深拷贝 浅拷贝/深拷贝 ...

  5. HTML5基本标签<搬运>

    HTML语言基本标签: 创建一个HTML文档<html></html> 设置文档标题以及其他不在WEB网页上显示的信息<head></head> 设置文 ...

  6. hibernate validator参数校验&自定义校验注解

    参数校验:简单的就逐个手动写代码校验,推荐用Valid,使用hibernate-validator提供的,如果参数不能通过校验,报400错误,请求格式不正确: 步骤1:在参数对象的属性上添加校验注解如 ...

  7. [洛谷P3261] [JLOI2015]城池攻占(左偏树)

    不得不说,这道题目是真的难,真不愧它的“省选/NOI-”的紫色大火题!!! 花了我晚自习前半节课看题解,写代码,又花了我半节晚自习调代码,真的心态爆炸.基本上改得和题解完全一样了我才过了这道题!真的烦 ...

  8. 2014 SummerTrain Beautiful Garden

    There are n trees planted in lxhgww's garden. You can assume that these trees are planted along the ...

  9. P3515 [POI2011]Lightning Conductor(决策单调性分治)

    P3515 [POI2011]Lightning Conductor 式子可转化为:$p>=a_j-a_i+sqrt(i-j) (j<i)$ $j>i$的情况,把上式翻转即可得到 下 ...

  10. owaspbwa tickets

    owaspbwa tickets 来源  https://sourceforge.net/p/owaspbwa/tickets/ 192 SQL Injection in pic_id paramet ...