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+5; const int B=18; const int M=N*2; inline int read(){int X=0,w=0;char ch=0;while(!isdigit(ch)){w|=ch=='-';ch=getchar();}while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();return w?-X:X; } struct node{int u[M],v[M],nxt[M];int cnt,head[N];void init(){cnt=0;memset(head,0,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+4],dep[N],pos[N],len[N],tot; void dfs(int u,int f){pos[u]=++tot;dep[u]=dep[f]+1;len[u]=len[f]+(u<=n);anc[u][0]=f;for(int i=1;i<=B;i++)anc[u][i]=anc[anc[u][i-1]][i-1];for(int i=e.head[u];i;i=e.nxt[i]){int v=e.v[i];if(v!=anc[u][0])dfs(v,u);} } inline int LCA(int i,int j){if(dep[i]<dep[j])swap(i,j);for(int k=B;k>=0;--k)if(dep[anc[i][k]]>=dep[j])i=anc[i][k];if(i==j)return i;for(int k=B;k>=0;--k)if(anc[i][k]!=anc[j][k])i=anc[i][k],j=anc[j][k];return anc[i][0]; }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+1,aux+t+1,cmp);num=t;stk[top=0]=0;for(int i=1;i<=t;i++){int u=aux[i];if(!top)fa_aux[u]=0,stk[++top]=u;else{int lca=LCA(u,stk[top]);while(dep[stk[top]]>dep[lca]){if(dep[stk[top-1]]<=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+1,aux+num+1,cmp); } int solve(){int ans=0;for(int i=num;i>1;i--){int u=aux[i],v=fa_aux[u];ans+=len[u]-len[v];}ans+=aux[1]<=n;return ans; } inline void init(){t=l=tot=0;e.init();g.init();memset(to,0,sizeof(to));memset(dfn,0,sizeof(dfn)); } int main(){int T=read();while(T--){init();n=read(),m=read();for(int i=1;i<=m;i++){int u=read(),v=read();g.add(u,v);g.add(v,u);}for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i,0);dfs(1,0);int q=read();while(q--){int t=read();for(int i=1;i<=t;i++)aux[i]=read();build(t);printf("%d\n",solve()-t);}}return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++
转载于:https://www.cnblogs.com/luyouqi233/p/9073672.html
BZOJ5329: [SDOI2018]战略游戏——题解相关推荐
- [BZOJ5329][Sdoi2018]战略游戏 圆方树+虚树
5329: [Sdoi2018]战略游戏 Time Limit: 30 Sec Memory Limit: 512 MB Submit: 174 Solved: 109 [Submit][Stat ...
- BZOJ5329:[SDOI2018]战略游戏(圆方树,虚树)
Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着 ...
- [BZOJ5329][SDOI2018]战略游戏
bzoj luogu Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任 ...
- LuoguP4606 [SDOI2018]战略游戏
LuoguP4606 [SDOI2018]战略游戏 题目描述 题目描述 省选临近,放飞自我的小 QQ 无心刷题,于是怂恿小 CC 和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由 nn 个城市 ...
- [SDOI2018]战略游戏
题目描述 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着道路走到 任意 ...
- 【题解】SDOI2018战略游戏
被CNST的大小卡了好久.一定要开到18呀-- 首先,遇到这种带各种各样环的图先考虑是不是可以建立圆方树,在圆方树上求出答案.然后转化为圆方树之后,我们就将图转化到了树上.答案非常的明显:只要一个圆点 ...
- Luogu4606 SDOI2018 战略游戏 圆方树、虚树、链并
传送门 弱化版 考虑到去掉一个点使得存在两个点不连通的形式类似割点,不难想到建立圆方树.那么在圆方树上对于给出的关键点建立虚树之后,我们需要求的就是虚树路径上所有圆点的数量减去关键点的数量. 因为没有 ...
- P4606 [SDOI2018]战略游戏
[题意] 给出一个无向图,q次询问,每次给定一个点集s代表占领点,问有多少个未被占领的点可以作为点集s中两个点u,v的割点 [分析] 首先,先建立圆方树,问题转化为能包含 给定点集 的最小连通块的 圆 ...
- [SDOI2018]战略游戏 圆方树+虚树
Description 给T组数据. 每组数据给你一个n个点的无向图,保证图联通,给q个询问. 每个询问给k个节点,问每一次询问中,求有多少个点在断掉他之后可以使图中两个点不连通. Sample In ...
最新文章
- 函数图像在图形计算机的应用,浅谈图形计算器在高中函数教学中的应用
- Android多点触摸交互处理,放大缩小图片
- jQuery选择器回顾,IE8还需要你发光发热
- MySQL-BETWEEN AND范围查询问题
- 有待试用,查看是谁锁住了我的数据库
- emacs python plugin_使用 python 扩展 emacs
- if语句 power query_PowerQuery学习:认识M函数
- ACL 2020 | 基于稠密段落检索的开放域问答系统技术
- Unity3D学习笔记之八为场景添加细节(一)
- swot分析法案例_(附数据集)SWOT分析实战案例!
- [转自李战博客]悟透JavaScript
- 消息通知的正向和反向
- vue3.0新特性及用法
- 构建之法读书笔记02
- 血管穿刺机器人研究汇总
- Java POI 导出 Excel 单元格 合并单元格 相邻的相同值 合并
- 安卓android按宽/高缩放图片到指定大小并进行裁剪得到中间部分图片
- 福建师范大学2022年2月课程考试《形势与政策》作业考核试题
- 【每天play】为了学好python需要从脚下做起,Linux基础-远程管理命令P50-60
- 被看穿本质的“圆形监狱”设想