Description

给定一张 \(n\) 个点 \(m\) 条边的无向联通图,共有 \(q\) 次操作,每次操作选择一些点作为关键点,询问有多少个点满足删去该点及与其相邻的边后,至少有两个关键点不能互相到达。\(n,q\leq 10^5,m\leq 2\cdot 10^5,\sum|S|\leq 2\cdot 10^5\)。

Sol

还是挺简单的。

就是圆方树+虚树\(\mathrm{DP}\)。

但是让我们看到了未来毒瘤的方向,出题人已经开始把树上问题放到图上了。

先把圆方树建出来,观察到两点之间的必经点就是圆方树上两点之间路径的圆点个数。

那就可以虚树\(\mathrm{DP}\)了,记录 \(dep[x]\) 表示从根到 \(x\) 有多少点是圆点,对于虚树上的每条边 \((x,y)\) 计算一下 \(dep[fa[y]]-dep[x]\) 就是这条边上圆点的贡献。然后再考虑在虚树上的点怎么计算,对于点 \(x\),如果 \(x\) 超过两个子树有关键点,或者 \(x\) 子树外还有关键点,那么 \(x\) 一定是必经点,随便判一下就好了。

然后调了一个小时的原因是倍增的 \(lg\) 数组只预处理到了 \(n\),但是建成圆方树之后深度有可能比 \(n\) 大。

Code

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef double db;
typedef long long ll;
const int N=8e5+5; int lg[N],d[N],f[N][20],ans,len;
int n,m,q,cnt,a[N],sze[N],dfn[N],low[N],head2[N];
int head[N],siz[N],dep[N],sum,stk[N],top,tot,is[N]; struct Edge{
int to,nxt;
}edge[N<<1],edge2[N<<1]; bool cmp(int x,int y){
return dfn[x]<dfn[y];
} void add(int x,int y){
edge[++cnt].to=y;
edge[cnt].nxt=head[x];
head[x]=cnt;
} void add2(int x,int y){
edge2[++cnt].to=y;
edge2[cnt].nxt=head2[x];
head2[x]=cnt;
} void tarjan(int now){
dfn[now]=low[now]=++tot;
stk[++top]=now;
for(int i=head[now];i;i=edge[i].nxt){
int to=edge[i].to;
if(!dfn[to]){
tarjan(to); low[now]=min(low[now],low[to]);
if(low[to]>=dfn[now]){
sum++; int z;
do{
z=stk[top--];
add2(sum,z),add2(z,sum);
} while(z!=to);
add2(sum,now),add2(now,sum);
}
} else low[now]=min(low[now],dfn[to]);
}
} void clear(){
cnt=tot=sum=top=0;
memset(d,0,sizeof d);
memset(f,0,sizeof f);
memset(is,0,sizeof is);
memset(dep,0,sizeof dep);
memset(dfn,0,sizeof dfn);
memset(low,0,sizeof low);
memset(stk,0,sizeof stk);
memset(sze,0,sizeof sze);
memset(head,0,sizeof head);
memset(head2,0,sizeof head2);
} void dfs(int now,int fa=0){
sze[now]=(now<=n); dfn[now]=++tot;
for(int i=head2[now];i;i=edge2[i].nxt){
int to=edge2[i].to;
if(fa==to) continue;
dep[to]=dep[now]+(to<=n);
f[to][0]=now; d[to]=d[now]+1;
for(int j=1;j<=lg[d[to]];j++) f[to][j]=f[f[to][j-1]][j-1];
dfs(to,now); sze[now]+=sze[to];
}
} int lca(int x,int y){
if(d[x]<d[y]) swap(x,y);
for(int j=lg[d[x]];~j;j--) if(d[f[x][j]]>=d[y]) x=f[x][j];
if(x==y) return x;
for(int j=lg[d[x]];~j;j--) if(f[x][j]!=f[y][j]) x=f[x][j],y=f[y][j];
return f[x][0];
} void ins(int x){
if(top<=1) return stk[++top]=x,void();
int LCA=lca(stk[top],x);
if(stk[top]==LCA) return stk[++top]=x,void();
while(top>1 and dfn[stk[top-1]]>=dfn[LCA]) add(stk[top-1],stk[top]),top--;
if(LCA!=stk[top]) add(LCA,stk[top]),stk[top]=LCA;
stk[++top]=x;
} void dfs2(int now){
siz[now]=(is[now]==q);
int flag=0;
for(int &i=head[now];i;i=edge[i].nxt){
int to=edge[i].to;
dfs2(to);
if(siz[to] and siz[to]!=len)
ans+=dep[f[to][0]]-dep[now],flag++;
siz[now]+=siz[to];
} if((siz[now]<len or flag>1) and now<=n and is[now]!=q) ans++;
} void work(){
scanf("%d",&len); ans=cnt=0;
for(int i=1;i<=len;i++)
scanf("%d",&a[i]),is[a[i]]=q;
std::sort(a+1,a+1+len,cmp);
top=0; if(is[1]!=q) stk[++top]=1;
for(int i=1;i<=len;i++) ins(a[i]);
while(top>1) add(stk[top-1],stk[top]),top--;
dfs2(1); printf("%d\n",ans);
} void solve(){
clear();
scanf("%d%d",&n,&m);sum=n;
for(int i=2;i<=n<<1;i++)
lg[i]=lg[i-1]+((1<<lg[i-1]+1)==i);
for(int x,y,i=1;i<=m;i++)
scanf("%d%d",&x,&y),add(x,y),add(y,x);
cnt=0; tarjan(1);
memset(head,0,sizeof head);
dep[1]=d[1]=1; tot=0; dfs(1);
for(scanf("%d",&q);q;work(),q--);
} signed main(){
int T;for(scanf("%d",&T);T;T--,solve());
return 0;
}

[SDOI2018] 战略游戏的更多相关文章

  1. [SDOI2018]战略游戏 圆方树,树链剖分

    [SDOI2018]战略游戏 这题是道路相遇(题解)的升级版,询问的两个点变成了\(S\)个点. LG传送门 还是先建出圆方树,考虑对于询问的\(S\)个点,答案就是圆方树上能包含这些点的最小连通块中 ...

  2. [bzoj5329] P4606 [SDOI2018]战略游戏

    P4606 [SDOI2018]战略游戏:广义圆方树 其实会了圆方树就不难,达不到黑,最多算个紫 那个转换到圆方树上以后的处理方法,画画图就能看出来,所以做图论题一定要多画图,并把图画清楚点啊!! 但 ...

  3. bzoj5315/luoguP4517 [SDOI2018]战略游戏(圆方树,虚树)

    bzoj5315/luoguP4517 [SDOI2018]战略游戏(圆方树,虚树) bzoj Luogu 题目描述略(太长了) 题解时间 切掉一个点,连通性变化. 上圆方树. $ \sum |S| ...

  4. BZOJ5329:[SDOI2018]战略游戏(圆方树,虚树)

    Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着 ...

  5. [BZOJ5329][SDOI2018]战略游戏

    bzoj luogu Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任 ...

  6. BZOJ5329: [SDOI2018]战略游戏——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=5329 https://www.luogu.org/problemnew/show/P4606 省选 ...

  7. bzoj 5329: [Sdoi2018]战略游戏

    Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着 ...

  8. luogu P4606 [SDOI2018]战略游戏

    LINK:战略游戏 一道很有价值的题目.这道题 一张无向联通图 每次询问给出K个关键点 问摧毁图中哪个点可以使得这K个关键的两两之间有一对不能联通 去掉的这个点不能是关键点 求方案数. 可以发现 当K ...

  9. 解题:SDOI2018 战略游戏

    题面 先圆方树然后建虚树,答案就是虚树大小.虚树没必要建出来,把原来的点的点权设为1,直接dfs序排序后相邻点求距离加上首尾两个点的距离,最后除以二(画一下可以发现是正反算了两遍),注意还要去掉询问点 ...

随机推荐

  1. Vue(二十八)el-cascader 动态加载 - 省市区组件

    1.后台接口为点击加载下一级 ,传省市区id <template> <el-cascader v-model="selectedOptions" placehol ...

  2. Java之hashCode的作用和equals方法的重构规则

    这个是博主对hashcode的初步理解,以后加深了会再来更新: 1.hashcode是什么? hashcode是对象的散列码,不同的对象几乎不一样,说几乎是因为还是可以一样的. 特点:每一个对象都有h ...

  3. 算法与数据结构(十二) 散列(哈希)表的创建与查找(Swift版)

    散列表又称为哈希表(Hash Table), 是为了方便查找而生的数据结构.关于散列的表的解释,我想引用维基百科上的解释,如下所示: 散列表(Hash table,也叫哈希表),是根据键(Key)而直 ...

  4. Java提高篇(三):内部类和匿名内部类

    一,内部类 其实内部类是十分简单的,我们根据其字里行间的意义就可以知道内部类应该是一个类当中的一个类,相当于一个类进行了嵌套,就如同循环的嵌套一般. 内部类有一个特征:内部类当中可以调用外部类当中的属 ...

  5. rem布局完成响应式开发,通俗且详细的原理解析和代码实现

    一.rem布局基本原理 原理:rem可以理解为一个长度单位,单位rem的值等于网页font-size的值.如果网页的字体大小为默认值16px,那么1rem就等于16px,0.5rem等于8px. 根据 ...

  6. Python程序里的注释和#号

    Python程序里的注释是很重要的.它们可以用自然语言告诉你某段代码的功能是什么.在你想要临时移除一段代码时,你还可以用注解的方式将这段代码临时禁用.接下来的练习将让你学会注释 : # A comme ...

  7. [Swift]LeetCode80. 删除排序数组中的重复项 II | Remove Duplicates from Sorted Array II

    Given a sorted array nums, remove the duplicates in-place such that duplicates appeared at most twic ...

  8. [SQL]LeetCode180. 连续出现的数字 | Consecutive Numbers

    SQL架构: Create table If Not Exists Logs (Id int, Num int) Truncate table Logs insert into Logs (Id, N ...

  9. SpringCloud微服务架构

    1.Eureka承载大规模系统每天千万级访问的原理 1).首先每个服务的eureka client组件默认30秒发送一个请求到eureka server拉取最近有变化的服务信息: 2).eureka还 ...

  10. iOS学习—— UISearchBar的使用

    转载自:http://blog.sina.com.cn/s/blog_7b9d64af0101dfg8.html 最近用到搜索功能.于是,经过不断的研究,终于,有点懂了. 那就来总结一下吧,好记性不如 ...