BZOJ5329: [SDOI2018]战略游戏——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=5329
https://www.luogu.org/problemnew/show/P4606
省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏。这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着道路走到任意其他城市。现在小C已经占领了其中至少两个城市,小Q可以摧毁一个小C没占领的城市,同时摧毁所有连接这个城市的道路。只要在摧毁这个城市之后能够找到某两个小C占领的城市u和v,使得从u出发沿着道路无论如何都不能走到v,那么小Q就能赢下这一局游戏。小Q和小C一共进行了q局游戏,每一局游戏会给出小C占领的城市集合S,你需要帮小Q数出有多少个城市在他摧毁之后能够让他赢下这一局游戏。
圆方树很好的板子题,以及最开始我题看错了以为是最少多少步才能赢emm…
看到炸点想到tarjan点双缩点,然后套上圆方树。
然后对于询问的点集发现很小,于是套上虚树。
然后任意两个关键点之间的赢法取决于这两个关键点之间有多少圆点,话句话讲,答案就是虚树所有路径在原树上的圆点个数和。
码码码就AC了。
PS:注意虚树的根到原树的根这段路程的圆点不要统计!WA在这里。
(以及强烈吐槽对于tarjan压栈压的是点的同学你们这样做是不对的!)
#include<cmath>
#include<queue>
#include<stack>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef double dl;
const int N=2e5+;
const int B=;
const int M=N*;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
struct node{
int u[M],v[M],nxt[M];
int cnt,head[N];
void init(){
cnt=;
memset(head,,sizeof(head));
}
void add(int U,int V){
u[++cnt]=U;v[cnt]=V;nxt[cnt]=head[U];head[U]=cnt;
}
}e,g;
int n,m;
int dfn[N],low[N],to[N],t,l;
stack<int>q;
void tarjan(int u,int f){
dfn[u]=low[u]=++t;
for(int i=g.head[u];i;i=g.nxt[i]){
int v=g.v[i];
if(!dfn[v]){
q.push(i);
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]){
int num;l++;
do{
num=q.top();q.pop();
int uu=g.u[num],vv=g.v[num];
if(to[uu]!=l){
to[uu]=l;
e.add(uu,l+n);e.add(l+n,uu);
}
if(to[vv]!=l){
to[vv]=l;
e.add(vv,l+n);e.add(l+n,vv);
}
}while(num!=i);
}
}else if(low[u]>dfn[v]&&f!=v){
q.push(i);
low[u]=dfn[v];
}
}
} int anc[N][B+],dep[N],pos[N],len[N],tot;
void dfs(int u,int f){
pos[u]=++tot;
dep[u]=dep[f]+;
len[u]=len[f]+(u<=n);
anc[u][]=f;
for(int i=;i<=B;i++)
anc[u][i]=anc[anc[u][i-]][i-];
for(int i=e.head[u];i;i=e.nxt[i]){
int v=e.v[i];
if(v!=anc[u][])dfs(v,u);
}
}
inline int LCA(int i,int j){
if(dep[i]<dep[j])swap(i,j);
for(int k=B;k>=;--k)
if(dep[anc[i][k]]>=dep[j])i=anc[i][k];
if(i==j)return i;
for(int k=B;k>=;--k)
if(anc[i][k]!=anc[j][k])
i=anc[i][k],j=anc[j][k];
return anc[i][];
} int aux[N],stk[N],fa_aux[N],top,num;
bool cmp(int a,int b){return pos[a]<pos[b];}
int build(int t){
sort(aux+,aux+t+,cmp);
num=t;stk[top=]=;
for(int i=;i<=t;i++){
int u=aux[i];
if(!top)fa_aux[u]=,stk[++top]=u;
else{
int lca=LCA(u,stk[top]);
while(dep[stk[top]]>dep[lca]){
if(dep[stk[top-]]<=dep[lca])
fa_aux[stk[top]]=lca;
top--;
}
if(stk[top]!=lca){
fa_aux[lca]=stk[top];
stk[++top]=lca;
aux[++num]=lca;
}
fa_aux[u]=lca;
stk[++top]=u;
}
}
sort(aux+,aux+num+,cmp);
}
int solve(){
int ans=;
for(int i=num;i>;i--){
int u=aux[i],v=fa_aux[u];
ans+=len[u]-len[v];
}
ans+=aux[]<=n;
return ans;
}
inline void init(){
t=l=tot=;
e.init();g.init();
memset(to,,sizeof(to));
memset(dfn,,sizeof(dfn));
}
int main(){
int T=read();
while(T--){
init();
n=read(),m=read();
for(int i=;i<=m;i++){
int u=read(),v=read();
g.add(u,v);g.add(v,u);
}
for(int i=;i<=n;i++)
if(!dfn[i])tarjan(i,);
dfs(,);
int q=read();
while(q--){
int t=read();
for(int i=;i<=t;i++)aux[i]=read();
build(t);
printf("%d\n",solve()-t);
}
}
return ;
}
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++
BZOJ5329: [SDOI2018]战略游戏——题解的更多相关文章
- BZOJ5329:[SDOI2018]战略游戏(圆方树,虚树)
Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着 ...
- [BZOJ5329][SDOI2018]战略游戏
bzoj luogu Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任 ...
- [bzoj5329] P4606 [SDOI2018]战略游戏
P4606 [SDOI2018]战略游戏:广义圆方树 其实会了圆方树就不难,达不到黑,最多算个紫 那个转换到圆方树上以后的处理方法,画画图就能看出来,所以做图论题一定要多画图,并把图画清楚点啊!! 但 ...
- [SDOI2018]战略游戏 圆方树,树链剖分
[SDOI2018]战略游戏 这题是道路相遇(题解)的升级版,询问的两个点变成了\(S\)个点. LG传送门 还是先建出圆方树,考虑对于询问的\(S\)个点,答案就是圆方树上能包含这些点的最小连通块中 ...
- bzoj5315/luoguP4517 [SDOI2018]战略游戏(圆方树,虚树)
bzoj5315/luoguP4517 [SDOI2018]战略游戏(圆方树,虚树) bzoj Luogu 题目描述略(太长了) 题解时间 切掉一个点,连通性变化. 上圆方树. $ \sum |S| ...
- bzoj 5329: [Sdoi2018]战略游戏
Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着 ...
- luogu P4606 [SDOI2018]战略游戏
LINK:战略游戏 一道很有价值的题目.这道题 一张无向联通图 每次询问给出K个关键点 问摧毁图中哪个点可以使得这K个关键的两两之间有一对不能联通 去掉的这个点不能是关键点 求方案数. 可以发现 当K ...
- 【题解】SDOI2018战略游戏
被CNST的大小卡了好久.一定要开到18呀…… 首先,遇到这种带各种各样环的图先考虑是不是可以建立圆方树,在圆方树上求出答案.然后转化为圆方树之后,我们就将图转化到了树上.答案非常的明显:只要一个圆点 ...
- 洛谷P4606 [SDOI2018]战略游戏 【圆方树 + 虚树】
题目链接 洛谷P4606 双倍经验:弱化版 题解 两点之间必经的点就是圆方树上两点之间的圆点 所以只需建出圆方树 每次询问建出虚树,统计一下虚树边上有多少圆点即可 还要讨论一下经不经过根\(1\)的情 ...
随机推荐
- 深入理解javascript原型链
在javascript中原型和原型链是一个很神奇的东西,对于大多数人也是最难理解的一部分,掌握原型和原型链的本质是javascript进阶的重要一环.今天我分享一下我对javascript原型和原型链 ...
- 「日常训练」Kefa and Park(Codeforces Round #321 Div. 2 C)
题意与分析(CodeForces 580C) 给你一棵树,然后每个叶子节点会有一家餐馆:你讨厌猫(waht?怎么会有人讨厌猫),就不会走有连续超过m个节点有猫的路.然后问你最多去几家饭店. 这题我写的 ...
- 获取ip地址以及获取城市等信息
class Program { static void Main(string[] args) { string ip = GetIP(); if (ip != null) { string city ...
- 如何编写 Python 程序
如何编写 Python 程序 从今以后,保存和运行 Python 程序的标准步骤如下: 对于 PyCharm 用户 打开 PyCharm. 以给定的文件名创建新文件. 输入案例中给出的代码. 右键并运 ...
- [JSON].value( keyPath )
语法:[JSON].value( keyPath ) 返回:[String | Null] 说明:获取指定键名路径值的字符串格式 示例: Set jsonObj = toJson("{bod ...
- 《Effective C++》读书笔记 条款03 尽可能使用const 使代码更加健壮
如果你对const足够了解,只需记住以下结论即可: 将某些东西声明为const可帮助编译器侦测出错误用法,const可被施加于任何作用于内的对象.函数参数.函数返回类型.成员函数本体. 编译器强制实施 ...
- Aizu - 2249
注意先保证距离最短,再来判断价格 邻接矩阵回朝内存 ,要用邻接表的 #include<bits/stdc++.h> using namespace std; #define inf 0x ...
- python常用函数—enumerate()
enumerate() 对于一个可迭代的(iterable)/可遍历的对象(如列表.字符串),enumerate将其组成一个索引序列,利用它可以同时获得索引和值的元组. 使用拆包,可以单独获得索引和值 ...
- Elasticsearch 评分score计算中的Boost 和 queryNorm
本来没有这篇文章,在公司分享ES的时候遇到一个问题,使用boost的时候,怎么从评分score中知道boost的影响. 虽然我们从查询结果可以直观看到,boost起了应有的作用,但是在explain的 ...
- ThinkPHP - 4 - 学习笔记(2015.4.12)
ThinkPHP D方法 D方法用于实例化自定义模型类,是ThinkPHP框架对Model类实例化的一种封装,并实现了单例模式,支持跨项目和分组调用,调用格式如下:D('[项目://][分组/]模型' ...