正题

题目链接: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]战略游戏【圆方树,虚树】的更多相关文章

  1. Luogu P4606 [SDOI2018] 战略游戏 圆方树 虚树

    https://www.luogu.org/problemnew/show/P4606 把原来的图的点双联通分量缩点(每个双联通分量建一个点,每个割点再建一个点)(用符合逻辑的方式)建一棵树(我最开始 ...

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

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

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

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

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

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

  5. Luogu4606 SDOI2018 战略游戏 圆方树、虚树、链并

    传送门 弱化版 考虑到去掉一个点使得存在两个点不连通的形式类似割点,不难想到建立圆方树.那么在圆方树上对于给出的关键点建立虚树之后,我们需要求的就是虚树路径上所有圆点的数量减去关键点的数量. 因为没有 ...

  6. BZOJ.5329.[SDOI2018]战略游戏(圆方树 虚树)

    题目链接 显然先建圆方树,方点权值为0圆点权值为1,两点间的答案就是路径权值和减去起点终点. 对于询问,显然可以建虚树.但是只需要计算两关键点间路径权值,所以不需要建出虚树.统计DFS序相邻的两关键点 ...

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

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

  8. 洛谷P4606 [SDOI2018]战略游戏 【圆方树 + 虚树】

    题目链接 洛谷P4606 双倍经验:弱化版 题解 两点之间必经的点就是圆方树上两点之间的圆点 所以只需建出圆方树 每次询问建出虚树,统计一下虚树边上有多少圆点即可 还要讨论一下经不经过根\(1\)的情 ...

  9. 洛谷P4606 [SDOI2018]战略游戏 [广义圆方树]

    传送门 思路 先考虑两点如何使他们不连通. 显然路径上所有的割点都满足条件. 多个点呢?也是这样的. 于是可以想到圆方树.一个点集的答案就是它的虚树里圆点个数减去点集大小. 可以把点按dfs序排序,然 ...

  10. 【SDOI2018】战略游戏(同时普及虚树)

    先看一道虚树普及题:给你一棵 $n$ 个点的树,$m$ 次询问,每次询问给你 $k$ 个关键点,求把这些点都连起来的路径并的最短长度.$1\le n,m\le 100000,\space 1\le \ ...

随机推荐

  1. Spring-Boot-Bean的使用,@Repository,@Service,@Controller,@Component

    前言 在Spring MVC的时候,我们使用xml来配置bean,如今的Spring boot推荐我们使用元注解的发生,那就听Spring Boot的推荐,下面我就为大家来介绍下Spring Boot ...

  2. jpa写原生sql-EntityManager

    废话不多说 package com.meeno.trainsys.meeting.service; import com.google.common.collect.Lists; import com ...

  3. Socket通信协议解析(文章摘要)

    参考网址: https://zhuanlan.zhihu.com/p/84800923 在计算机通信领域,socket 被翻译为"套接字",它是计算机之间进行通信的一种约定或一种方 ...

  4. .NET Core:处理全局异常

    一.前言 在程序设计中,我们会遇到各种各样的异常问题,一个好的异常处理解决方案能够帮助开发者快速的定位问题,也能够给用户更好的用户体验.那么我们在AspNetCore中该如何捕获和处理异常呢?我们以一 ...

  5. 使用javascript纯前端导出excel

    前言(感谢技术的分享者) 参考博客地址 github地址 由SheetJS出品的js-xlsx是一款非常方便的只需要纯JS即可读取和导出excel的工具库,功能强大,支持格式众多,支持xls.xlsx ...

  6. 使用servlet中是否需要考虑线程问题

    package day09; import java.io.IOException; import javax.servlet.ServletException; import javax.servl ...

  7. sparksql解析流程

    1.sparkSql处理核心:Catalyst工作流程(本质:把sql.dataframe相结合,以树tree的形式来存储.优化) 2.catalyst工作流程 1)Parser(解析器):SqlPa ...

  8. 🏆【Alibaba微服务技术系列】「Dubbo3.0技术专题」回顾Dubbo2.x的技术原理和功能实现及源码分析(温故而知新)

    RPC服务 什么叫RPC? RPC[Remote Procedure Call]是指远程过程调用,是一种进程间通信方式,他是一种技术的思想,而不是规范.它允许程序调用另一个地址空间(通常是共享网络的另 ...

  9. SpringMVC IO 文件上传

    1 public class FileUtil { 2 3 4 /** 5 * 读取文件内容,作为字符串返回 6 */ 7 public static String readFileAsString( ...

  10. 轻松搞定webpack5.x

    源码地址:https://gitee.com/cyp926/webpack-project.git "webpack": "^5.46.0", "we ...