[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条连接这些城市的双向道路构成,并且从任 ...
随机推荐
- nutz中实现登录验证
一.nutz是什么 nutz是一个轻便的web端开发框架.主页如下:http://www.nutzam.com/core/nutz_preface.html 二.session简单介绍 大家都知道ht ...
- asp.net--CRSF
asp.net使用了token来防止CRSF攻击 前台: 使用@Html.AntiForgeryToken(); 浏览器里面被存了一个cookie值,这个值是asp.net存给浏览器的,是readon ...
- matplotlib的cmap
今天又看到了这样的代码: plt.imshow(X_train[0], cmap=plt.get_cmap('PuBuGn_r')) #plt.imshow(X_train[0], cmap=plt. ...
- [Angular] Increasing Performance by using Pipe
For example you make a function to get rating; getRating(score: number): string { let rating: string ...
- Node.js具体解析
介绍 JavaScript 高涨的人气带来了非常多变化.以至于现在使用其进行网络开发的形式也变得截然不同了.就如同在浏览器中一样,现在我们也能够在server上执行 JavaScript ,从前端跨越 ...
- android小技巧:在activity中实现与绑定的fragment的回调
看到标题你可能会想是一个多么高大上的技巧呢?事实上非常一般就是自己定义回调函数. 首先我们知道activity之间的数据传递有几种方式: 一是startActivityForResut()启动一个ac ...
- 【cl】Unable to find executable for: taskkill
十二月 02, 2015 5:16:56 下午 org.openqa.selenium.os.ProcessUtils killWinProcess警告: Process refused to die ...
- ios swift学习日记4-字符串和字符
近期ios的swift语言好像火了起来,本人没有objectc的基础,但之前是有c跟java的基础的. 从这几天開始学习ios的swift语言,后期以博客形式公布.这里提供一本翻译的英文版的swif书 ...
- 使用Micrisoft.net设计方案 第一章 企业解决方案中构建设计模式
第一章企业解决方案中构建设计模式 我们知道的系统总是由简单到复杂,而不是直接去设计一个复杂系统.如果直接去设计一个复杂系统,结果最终会导致失败.在设计系统的时候,先设计一个能够正常工作的系统,然后在此 ...
- [hihocoder][Offer收割]编程练习赛45
互补二元组 Xi + Xj = Yi + Yj等价于Xi - Yi + Xj - Yj = 0 ,对每个二元组计算其x与y的差,每次加上其相反数的个数. #pragma comment(linker, ...