喜闻乐见的圆方树+虚树

图上不好做,先建出圆方树。

然后答案就是没被选到的且至少有两条边可以走到被选中的点的圆点的数量。

语文不好,但结论画画图即可得出。

然后套路建出虚树。

发现在虚树上DP可以得出答案。

所以在虚树上DP即可。

代码极丑

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=401000;
struct Graph{
struct edge{
int to,nxt;
}e[N*2];
int cnt,head[N];
void add_edge(int u,int v){
cnt++;
e[cnt].nxt=head[u];
e[cnt].to=v;
head[u]=cnt;
}
}g1,g2,g3;
int dfn[N],low[N],tim,stack[N],top,num;
void Tarjan(int u){
dfn[u]=low[u]=++tim;
stack[++top]=u;
for(int i=g1.head[u];i;i=g1.e[i].nxt){
int v=g1.e[i].to;
if(dfn[v]==0){
Tarjan(v);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]){
g2.add_edge(++num,u);
g2.add_edge(u,num);
int x;
do{
x=stack[top--];
g2.add_edge(x,num);
g2.add_edge(num,x);
}while(x!=v);
}
}
else low[u]=min(low[u],dfn[v]);
}
}
int w[N],fa[N][22],dep[N],tot,n;
void dfs(int u,int f){
w[u]=w[f]+(u<=n?1:0);
fa[u][0]=f;dep[u]=dep[f]+1;dfn[u]=++tot;
for(int i=1;i<=20;i++)fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=g2.head[u];i;i=g2.e[i].nxt){
int v=g2.e[i].to;
if(v==f)continue;
dfs(v,u);
}
}
bool cmp(int x,int y){
return dfn[x]<dfn[y];
}
int getlca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
for(int i=20;i>=0;i--)
if(dep[fa[x][i]]>=dep[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];
}
int q[N],Tot;
void ins(int x){
if(top<=1){stack[++top]=x;return;}
int lca=getlca(stack[top],x);
if(lca==stack[top]){stack[++top]=x;return;}
while(top&&dfn[stack[top-1]]>=dfn[lca])g3.add_edge(stack[top-1],stack[top]),top--;
if(stack[top]!=lca)g3.add_edge(lca,stack[top]),stack[top]=lca,q[++Tot]=lca;
stack[++top]=x;
}
int ans;
bool book[N];
void get_ans(int u){
if(u==1&&book[u]==0){
int tmp=0;
for(int i=g3.head[u];i;i=g3.e[i].nxt)tmp++;
if(tmp==1){
for(int i=g3.head[u];i;i=g3.e[i].nxt){
int v=g3.e[i].to;
get_ans(v);
}
return;
}
}
if(!book[u]&&u<=n)ans++;
for(int i=g3.head[u];i;i=g3.e[i].nxt){
int v=g3.e[i].to;
ans+=w[v]-w[u];
if(v<=n)ans--;
get_ans(v);
}
}
void clear(){
while(Tot)book[q[Tot]]=g3.head[q[Tot]]=0,Tot--;
g3.cnt=0;top=0;ans=0;
}
void init(){
memset(g1.head,0,sizeof(g1.head));
g1.cnt=0;
memset(g2.head,0,sizeof(g2.head));
g2.cnt=0;
tim=0;top=0;tot=0;
memset(dfn,0,sizeof(dfn));
}
int read(){
int sum=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
return sum*f;
}
int m,Q,a[N];
int main(){
// freopen("xdx.out","w",stdout);
int T=read();
while(T--){
init();
num=n=read();m=read();
for(int i=1;i<=m;i++){
int u=read(),v=read();
g1.add_edge(u,v);g1.add_edge(v,u);
}
Tarjan(1);
dfs(1,0);
Q=read();
while(Q--){
clear();
int k=read();
for(int i=1;i<=k;i++)a[i]=read(),book[a[i]]=1,q[++Tot]=a[i];
sort(a+1,a+1+k,cmp);
if(a[1]!=1)stack[++top]=1,q[++Tot]=1;
for(int i=1;i<=k;i++)ins(a[i]);
for(int i=1;i<top;i++)g3.add_edge(stack[i],stack[i+1]);
get_ans(1);
printf("%d\n",ans);
}
}
return 0;
}

[SDOI2018]战略游戏(圆方树+虚树)的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. 仙人掌 && 圆方树 && 虚树 总结

    仙人掌 && 圆方树 && 虚树 总结 Part1 仙人掌 定义 仙人掌是满足以下两个限制的图: 图完全联通. 不存在一条边处在两个环中. 其中第二个限制让仙人掌的题做 ...

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

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

随机推荐

  1. asp.net--CRSF

    asp.net使用了token来防止CRSF攻击 前台: 使用@Html.AntiForgeryToken(); 浏览器里面被存了一个cookie值,这个值是asp.net存给浏览器的,是readon ...

  2. Docker--微软dotconf截图

  3. [bzoj1055][HAOI2008]玩具取名_区间dp

    玩具取名 bzoj-1055 HAOI-2008 题目大意:给你一个用W,I,N,G组成的字符串,给你一些这四个字符之间的变换规则,每一个变换规则都是由一个字符变成两个字符,问这个字符串是否可能是由一 ...

  4. Spring MVC-表单(Form)标签-复选框(Checkbox)示例(转载实践)

    以下内容翻译自:https://www.tutorialspoint.com/springmvc/springmvc_checkbox.htm 说明:示例基于Spring MVC 4.1.6. 以下示 ...

  5. Linux磁盘分区方案(转)

    硬盘分区的各个分区的意义 尽管可以根据我们已经提到的分区原则,Linux装在一个单一的大分区中,但更好的主意是将它分开.综合了单一分区的简单性和多分区的灵活性,我们推荐以下配置.请注意:如果你想安装L ...

  6. ArcEngine 地图导航 查找路径 经纬度坐标导航 最优路径分析

    本文来自CSDN博客.转载请标明出处 http//blog.csdn.net/zdb330906531 需求:依据经纬度坐标.取得两个起点与终点,显示最优路径实现导航. 參考官方样例后.我在arcMa ...

  7. Java使用JAVE获取MP4播放时长

  8. oc18--self1

    // // Iphone.h // day13 #import <Foundation/Foundation.h> typedef enum { kFlahlightStatusOpen, ...

  9. 轻快的vim(四):修改

    我想每个Coder都深刻的明白,修改这一操作在代码的世界里是多么重要 与其说修改,无非就是删除了再插入,但VIM把这两者结合的很有效率 闲话少说,让我们再次使用这轻快的VIM在code上起舞 字符替换 ...

  10. [BZOJ 3387] Fence Obstacle Course

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=3387 [算法] f[i][0]表示从第i个栅栏的左端点走到原点的最少移动步数 f[i ...