P4606-[SDOI2018]战略游戏【圆方树,虚树】
正题
题目链接:https://www.luogu.com.cn/problem/P4606
题目大意
给出\(n\)个点\(m\)条边的一张图,\(q\)次询问给出一个点集,询问有多少个点割掉后可以是点集中至少一个点对不连通。
解题思路
就是问圆方树上的虚树中的圆点数量,照着统计就好了。
细节有点多,注意不要习惯性的把根节点带进虚树就好了。
时间复杂度\(O(n\log n)\)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
const int N=2e5+10;
int T,n,m,q,dfc,cnt,ans,p[N],dfn[N],low[N],s[N];
int pn,dis[N],dep[N],fa[N],top[N],siz[N],son[N];
vector<int> G[N],H[N];stack<int> S;
void tarjan(int x){
dfn[x]=low[x]=++dfc;S.push(x);
for(int i=0;i<H[x].size();i++){
int y=H[x][i];
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
if(low[y]==dfn[x]){
int k;++n;
do{
k=S.top();S.pop();
G[n].push_back(k);
G[k].push_back(n);
}while(k!=y);
G[n].push_back(x);
G[x].push_back(n);
}
}
else low[x]=min(low[x],dfn[y]);
}
return;
}
void dfs1(int x){
dfn[x]=++dfc;siz[x]=1;
dep[x]=dep[fa[x]]+1;
dis[x]=dis[fa[x]]+(x<=pn);
for(int i=0;i<G[x].size();i++){
int y=G[x][i];
if(y==fa[x])continue;
fa[y]=x;dfs1(y);siz[x]+=siz[y];
if(siz[y]>siz[son[x]])son[x]=y;
}
return;
}
void dfs2(int x){
if(son[x]){
top[son[x]]=top[x];
dfs2(son[x]);
}
for(int i=0;i<G[x].size();i++){
int y=G[x][i];
if(y==fa[x]||y==son[x])continue;
top[y]=y;dfs2(y);
}
return;
}
int LCA(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=fa[top[x]];
}
return (dep[x]<dep[y])?x:y;
}
void Add(int x){
if(!cnt){s[++cnt]=x;return;}
int lca=LCA(x,s[cnt]);
while(cnt>1&&dep[s[cnt-1]]>dep[lca])
ans+=dis[s[cnt]]-dis[s[cnt-1]],cnt--;
if(dep[s[cnt]]>dep[lca])
ans+=dis[s[cnt]]-dis[lca],cnt--;
if(s[cnt]!=lca)s[++cnt]=lca;
s[++cnt]=x;return;
}
bool cmp(int x,int y)
{return dfn[x]<dfn[y];}
int main()
{
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);dfc=0;pn=n;
for(int i=1;i<=2*n;i++)
H[i].clear(),G[i].clear(),dfn[i]=low[i]=son[i]=0;
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
H[x].push_back(y);
H[y].push_back(x);
}
tarjan(1);dfc=0;
dfs1(1);top[1]=1;dfs2(1);
scanf("%d",&q);
while(q--){
scanf("%d",&m);
for(int i=1;i<=m;i++)scanf("%d",&p[i]);
sort(p+1,p+1+m,cmp);cnt=ans=0;
// if(p[1]!=1)s[++cnt]=1;
for(int i=1;i<=m;i++)
Add(p[i]);
while(cnt>1)ans+=dis[s[cnt]]-dis[s[cnt-1]],cnt--;
printf("%d\n",ans-m+(LCA(p[1],p[m])<=pn));
}
}
return 0;
}
P4606-[SDOI2018]战略游戏【圆方树,虚树】的更多相关文章
- Luogu P4606 [SDOI2018] 战略游戏 圆方树 虚树
https://www.luogu.org/problemnew/show/P4606 把原来的图的点双联通分量缩点(每个双联通分量建一个点,每个割点再建一个点)(用符合逻辑的方式)建一棵树(我最开始 ...
- bzoj5315/luoguP4517 [SDOI2018]战略游戏(圆方树,虚树)
bzoj5315/luoguP4517 [SDOI2018]战略游戏(圆方树,虚树) bzoj Luogu 题目描述略(太长了) 题解时间 切掉一个点,连通性变化. 上圆方树. $ \sum |S| ...
- [SDOI2018]战略游戏 圆方树,树链剖分
[SDOI2018]战略游戏 这题是道路相遇(题解)的升级版,询问的两个点变成了\(S\)个点. LG传送门 还是先建出圆方树,考虑对于询问的\(S\)个点,答案就是圆方树上能包含这些点的最小连通块中 ...
- BZOJ5329:[SDOI2018]战略游戏(圆方树,虚树)
Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着 ...
- Luogu4606 SDOI2018 战略游戏 圆方树、虚树、链并
传送门 弱化版 考虑到去掉一个点使得存在两个点不连通的形式类似割点,不难想到建立圆方树.那么在圆方树上对于给出的关键点建立虚树之后,我们需要求的就是虚树路径上所有圆点的数量减去关键点的数量. 因为没有 ...
- BZOJ.5329.[SDOI2018]战略游戏(圆方树 虚树)
题目链接 显然先建圆方树,方点权值为0圆点权值为1,两点间的答案就是路径权值和减去起点终点. 对于询问,显然可以建虚树.但是只需要计算两关键点间路径权值,所以不需要建出虚树.统计DFS序相邻的两关键点 ...
- [bzoj5329] P4606 [SDOI2018]战略游戏
P4606 [SDOI2018]战略游戏:广义圆方树 其实会了圆方树就不难,达不到黑,最多算个紫 那个转换到圆方树上以后的处理方法,画画图就能看出来,所以做图论题一定要多画图,并把图画清楚点啊!! 但 ...
- 洛谷P4606 [SDOI2018]战略游戏 【圆方树 + 虚树】
题目链接 洛谷P4606 双倍经验:弱化版 题解 两点之间必经的点就是圆方树上两点之间的圆点 所以只需建出圆方树 每次询问建出虚树,统计一下虚树边上有多少圆点即可 还要讨论一下经不经过根\(1\)的情 ...
- 洛谷P4606 [SDOI2018]战略游戏 [广义圆方树]
传送门 思路 先考虑两点如何使他们不连通. 显然路径上所有的割点都满足条件. 多个点呢?也是这样的. 于是可以想到圆方树.一个点集的答案就是它的虚树里圆点个数减去点集大小. 可以把点按dfs序排序,然 ...
- 【SDOI2018】战略游戏(同时普及虚树)
先看一道虚树普及题:给你一棵 $n$ 个点的树,$m$ 次询问,每次询问给你 $k$ 个关键点,求把这些点都连起来的路径并的最短长度.$1\le n,m\le 100000,\space 1\le \ ...
随机推荐
- null的坑 和 比较运算符、相等运算符的隐式转换问题 (在javascript中,null>=0 为真,null<=0 为真,null==0却为假,null到底是什么?)
null在关系运算中的坑 & 关系运算符的隐式转换问题 注意: 比较运算符 和 相等运算符 的 ECMAscript 语法实现不同. 比较运算符 和 相等运算符 对数据进行了隐式转换, 相当于 ...
- Spring详解------概述
1.什么是 Spring ? Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2E ...
- JDBC基础篇(MYSQL)——通过JDBC连接数据库的三种方式
package day01_jdbc; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManage ...
- MongoDB学习笔记一(MongoDB介绍 + 基本指令 + 查询语句)
什么是MongoDB MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统. 在高负载的情况下,添加更多的节点,可以保证服务器性能. MongoDB 旨在为WEB应用提供可扩 ...
- validity属性返回对象中的属性值
- T-SQL - query03_去重查询|模糊查询|排序|分组|使用函数
时间:2017-09-29 整理:byzqy 本篇仍以"梁山好汉"数据表为例,介绍几个常用的 T-SQL 查询语句: 去重查询,关键字:distinct 使用通配符模糊查询,关键字 ...
- NX二次开发-创建NX9 NXOpenCPP Wizard开发向导模板
这篇文章,我在CSDN,在唐工论坛都发过.http://www.nxopen.cn/forum.php?mod=viewthread&tid=2039&highlight=NX9 博客 ...
- https(ssl) 免费证书
https://letsencrypt.org/getting-started/ https://certbot.eff.org/lets-encrypt/centosrhel7-nginx http ...
- Tars | 第4篇 Subset路由规则业务分析与源码探索
目录 前言 1. Subset不是负载均衡 1.1 任务需求 1.2 负载均衡源码结构图 1.3 负载均衡四种调用器 1.4 新增两种负载均衡调用器 1.5 Subset应该是"过滤&quo ...
- elementui table的新增,编辑和删除
\ 新增 this.tableData.unshift(data); 编辑 this.$set(this.tableData,data.index,data); 删除 rows.splice(inde ...