【题解】SDOI2018战略游戏
被CNST的大小卡了好久。一定要开到18呀……
首先,遇到这种带各种各样环的图先考虑是不是可以建立圆方树,在圆方树上求出答案。然后转化为圆方树之后,我们就将图转化到了树上。答案非常的明显:只要一个圆点位于一个节点到另一个节点的路径上,它就是一个可以选择的答案点。
又观察到数据范围中给出的总和 <= & 多组询问的模式,立马联想到建立虚树。建立出了虚树,我们发现这棵虚树有一个非常妙妙的性质:所有的叶子节点均为指定点。这样的话,在这棵虚树上所有的点(从叶子到根的路径上的点,包括没有建出来的点)均为合法的答案。不过要注意到因为我们自动建立出了1点为根节点,所以要防止1没有被选择,要减去这一段非法的点数。
// luogu-judger-enable-o2
#include <bits/stdc++.h>
using namespace std;
#define maxn 200000
#define CNST 19
int n, m, K, tot, T;
int timer, dfn[maxn], low[maxn];
int dep[maxn], dis[maxn], gra[maxn][CNST];
int ans, S[maxn], a[maxn];
bool vis[maxn]; struct edge
{
int cnp = , head[maxn], to[maxn * ], last[maxn * ];
void add(int u, int v)
{
if(u == v) return;
to[cnp] = v, last[cnp] = head[u], head[u] = cnp ++;
to[cnp] = u, last[cnp] = head[v], head[v] = cnp ++;
}
void Clear()
{
cnp = ; memset(head, , sizeof(head));
}
}E1, E2, E3; int read()
{
int x = , k = ;
char c;
c = getchar();
while(c < '' || c > '') { if(c == '-') k = -; c = getchar(); }
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * k;
} void Tarjan(int u)
{
dfn[u] = low[u] = ++ timer; S[++ S[]] = u;
for(int i = E1.head[u]; i; i = E1.last[i])
{
int v = E1.to[i];
if(!dfn[v])
{
Tarjan(v); low[u] = min(low[u], low[v]);
if(low[v] >= dfn[u])
{
E2.add(++ tot, u); int x = ;
do
{
x = S[S[] --]; E2.add(tot, x);
}while(x != v);
}
}
else low[u] = min(low[u], dfn[v]);
}
} void dfs(int u, int fa)
{
dis[u] = , dep[u] = ;
gra[u][] = fa, dfn[u] = ++ timer, dep[u] = dep[fa] + ;
if(u <= n) dis[u] += ; dis[u] += dis[fa];
for(int i = ; i < CNST; i ++) gra[u][i] = gra[gra[u][i - ]][i - ];
for(int i = E2.head[u]; i; i = E2.last[i])
{
int v = E2.to[i];
if(v != fa) dfs(v, u);
}
} int LCA(int x, int y)
{
if(dep[x] < dep[y]) swap(x, y);
for(int i = CNST - ; ~i; i --)
if(dep[gra[x][i]] >= dep[y]) x = gra[x][i];
for(int i = CNST - ; ~i; i --)
if(gra[x][i] != gra[y][i])
x = gra[x][i], y = gra[y][i];
return x == y ? x : gra[x][];
} bool cmp(int a, int b)
{
return dfn[a] < dfn[b];
} void DP(int u, int fa)
{
for(int i = E3.head[u]; i; i = E3.last[i])
{
int v = E3.to[i];
if(v == fa) continue;
DP(v, u); ans += dis[v] - dis[u];
}
E3.head[u] = ;
} void Work()
{
E3.cnp = ;
K = read(), tot = , S[] = , S[] = ;
for(int i = ; i <= K; i ++) a[i] = read();
sort(a + , a + + K, cmp);
int L = a[];
for(int i = ; i <= K; i ++)
{
int lca = LCA(S[S[]], a[i]);
L = LCA(L, a[i]);
while()
{
if(dep[lca] >= dep[S[S[] - ]])
{
E3.add(S[S[]], lca); S[] --;
if(lca != S[S[]]) S[++ S[]] = lca;
break;
}
if(S[]) E3.add(S[S[]], S[S[] - ]), S[] --;
}
S[++ S[]] = a[i];
}
while(S[] > ) E3.add(S[S[]], S[S[] - ]), S[] --;
ans = ; DP(, );
if(L > n) printf("%d\n", ans - dis[L] + - K);
else printf("%d\n", ans - dis[L] + - K);
} void init()
{
E1.Clear(), E2.Clear(), timer = ;
memset(gra, , sizeof(gra));
} int main()
{
scanf("%d", &T);
while(T --)
{
init();
tot = n = read(), m = read();
for(int i = ; i <= n; i ++) dfn[i] = low[i] = ;
for(int i = ; i <= m; i ++)
{
int u = read(), v = read();
E1.add(u, v);
}
S[] = , Tarjan();
int Q = read();
timer = ; dfs(, );
for(int i = ; i <= Q; i ++) Work();
}
return ;
}
【题解】SDOI2018战略游戏的更多相关文章
- [SDOI2018]战略游戏 圆方树,树链剖分
[SDOI2018]战略游戏 这题是道路相遇(题解)的升级版,询问的两个点变成了\(S\)个点. LG传送门 还是先建出圆方树,考虑对于询问的\(S\)个点,答案就是圆方树上能包含这些点的最小连通块中 ...
- bzoj5315/luoguP4517 [SDOI2018]战略游戏(圆方树,虚树)
bzoj5315/luoguP4517 [SDOI2018]战略游戏(圆方树,虚树) bzoj Luogu 题目描述略(太长了) 题解时间 切掉一个点,连通性变化. 上圆方树. $ \sum |S| ...
- [bzoj5329] P4606 [SDOI2018]战略游戏
P4606 [SDOI2018]战略游戏:广义圆方树 其实会了圆方树就不难,达不到黑,最多算个紫 那个转换到圆方树上以后的处理方法,画画图就能看出来,所以做图论题一定要多画图,并把图画清楚点啊!! 但 ...
- BZOJ5329: [SDOI2018]战略游戏——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=5329 https://www.luogu.org/problemnew/show/P4606 省选 ...
- BZOJ5329:[SDOI2018]战略游戏(圆方树,虚树)
Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着 ...
- [BZOJ5329][SDOI2018]战略游戏
bzoj luogu Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任 ...
- bzoj 5329: [Sdoi2018]战略游戏
Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着 ...
- luogu P4606 [SDOI2018]战略游戏
LINK:战略游戏 一道很有价值的题目.这道题 一张无向联通图 每次询问给出K个关键点 问摧毁图中哪个点可以使得这K个关键的两两之间有一对不能联通 去掉的这个点不能是关键点 求方案数. 可以发现 当K ...
- 洛谷P4606 [SDOI2018]战略游戏 【圆方树 + 虚树】
题目链接 洛谷P4606 双倍经验:弱化版 题解 两点之间必经的点就是圆方树上两点之间的圆点 所以只需建出圆方树 每次询问建出虚树,统计一下虚树边上有多少圆点即可 还要讨论一下经不经过根\(1\)的情 ...
随机推荐
- Ubuntu 16.04 swoole扩展安装注意!!!
前言:目前很多项目估计常常会用到swoole扩展,如个人使用Ubuntu虚拟机安装扩展,这里总结一下遇到的问题: 一.先保证服务器时间同步当前地区时间,如北京时间: 1.设定时区 如:设定时区:dpk ...
- unity开发c#代码
1.摄像头跟随主角移动,并支持旋转. 开发过程中需要摄像头以一定距离跟随player,同时会进行旋转,属于一种常见的跟随方式. using UnityEngine; using System.Coll ...
- 【EXCEL】SUMIFS(複数の条件を指定して数値を合計する)
分享:
- 2007: [Noi2010]海拔
2007: [Noi2010]海拔 https://www.lydsy.com/JudgeOnline/problem.php?id=2007 分析: 平面图最小割. S在左下,T在右上,从S到T的一 ...
- 判断电脑CPU硬件支不支持64位
你可以在注册表中查看: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment\PROCESSO ...
- Python 常见的字符串操作
1.strip.lstrip和rstrip 描述: 用于移除字符串左右两边.左边.右边指定的字符(默认为空白符,例如:/n, /r, /t, ' ')或字符序列. 语法: str.strip([cha ...
- 常用模块(chardet)
作用:检测二进制的编码格式,不是百分百正确 import chardet f = open('test.txt', 'rb')data = f.read()print(data)result = ch ...
- 杜绝网上压根没测过就乱写之 《oracle mybatis 返回自增主键 》
面试过好多人,包括自己也属于这么一个情况: 遇到问题直接去网上查,一般都可以查到解决方案.其中也包括一些基本的面试资料的答案. 其实有很多答案也都是正确的,但是还是存在一些压根就是胡乱抄来的答案,也不 ...
- Leetcode 55. Jump Game & 45. Jump Game II
55. Jump Game Description Given an array of non-negative integers, you are initially positioned at t ...
- Linux下的命令行
一.文件传输(两种方式) 1. 使用CRT传输 1. 一定要修改编码为UTF-8类型 1. 按住alt + p 切换成传输文件的窗口,然后拖拽文件进来即可 2. 使用类似xftp这种软件传输 这种软件 ...