[SDOI2018]战略游戏(圆方树+虚树)
喜闻乐见的圆方树+虚树
图上不好做,先建出圆方树。
然后答案就是没被选到的且至少有两条边可以走到被选中的点的圆点的数量。
语文不好,但结论画画图即可得出。
然后套路建出虚树。
发现在虚树上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]战略游戏(圆方树+虚树)的更多相关文章
- 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序相邻的两关键点 ...
- Luogu P4606 [SDOI2018] 战略游戏 圆方树 虚树
https://www.luogu.org/problemnew/show/P4606 把原来的图的点双联通分量缩点(每个双联通分量建一个点,每个割点再建一个点)(用符合逻辑的方式)建一棵树(我最开始 ...
- 【SDOI2018】战略游戏(同时普及虚树)
先看一道虚树普及题:给你一棵 $n$ 个点的树,$m$ 次询问,每次询问给你 $k$ 个关键点,求把这些点都连起来的路径并的最短长度.$1\le n,m\le 100000,\space 1\le \ ...
- 仙人掌 && 圆方树 && 虚树 总结
仙人掌 && 圆方树 && 虚树 总结 Part1 仙人掌 定义 仙人掌是满足以下两个限制的图: 图完全联通. 不存在一条边处在两个环中. 其中第二个限制让仙人掌的题做 ...
- [BZOJ5329][SDOI2018]战略游戏
bzoj luogu Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任 ...
随机推荐
- 20150805-20150807 tradeDate-----python
1.创建数据库(strategy).表(trade_date 交易日) create database strategy default character set utf8 collate utf8 ...
- Docker 入门,镜像,安装, 数据,网络,配置
https://yeasy.gitbooks.io/docker_practice/basic_concept/image.html
- /tmp目录下执行脚本失败提示Permission denied
Linux上执行Shell脚本运行失败提示Permission denied一个问题,挺好的问题,切中了知识盲点. 问题现象 Shell脚本在/tmp目录下,执行./test.sh运行失败,提示Per ...
- Storm工作流程 vs. Spark Stream
看的这个学习课程: http://study.163.com/course/courseLearn.htm?courseId=1002887002#/learn/video?lessonId=1003 ...
- 【FastDev4Android框架开发】打造QQ6.X最新版本号側滑界面效果(三十八)
转载请标明出处: http://blog.csdn.net/developer_jiangqq/article/details/50253925 本文出自:[江清清的博客] (一).前言: [好消息] ...
- LINQ查询知识总结
-------适合自己的才是最好的!!! LINQ查询知识总结:案例分析 案例:汽车表car,系列表brand,厂商表productor private MyCarDataContext _Cont ...
- HDU 1143 Tri Tiling
链接:http://acm.hdu.edu.cn/showproblem.php? pid=1143 Tri Tiling Time Limit: 2000/1000 MS (Java/Others) ...
- 【C++/数据结构】顺序表的基本操作
<span style="font-size:18px;"><strong>#pragma once #include <iostream> u ...
- BZOJ 4517: [Sdoi2016]排列计数 错排+逆元
4517: [Sdoi2016]排列计数 Description 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i, ...
- 各种JSON的maven引用
一.jackjson maven <jackjson.version>2.8.8</jackjson.version> <dependency> <group ...