洛谷P4606 [SDOI2018]战略游戏 【圆方树 + 虚树】
题目链接
题解
两点之间必经的点就是圆方树上两点之间的圆点
所以只需建出圆方树
每次询问建出虚树,统计一下虚树边上有多少圆点即可
还要讨论一下经不经过根\(1\)的情况
P4606
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 200005,maxm = 100005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int h[maxn],ne = 1,hh[maxn],Ne = 1;
struct EDGE{int to,nxt;}ed[maxn << 2],e[maxn << 2];
inline void build(int u,int v){
e[++Ne] = (EDGE){v,hh[u]}; hh[u] = Ne;
e[++Ne] = (EDGE){u,hh[v]}; hh[v] = Ne;
}
inline void add(int u,int v){
ed[++ne] = (EDGE){v,h[u]}; h[u] = ne;
ed[++ne] = (EDGE){u,h[v]}; h[v] = ne;
}
int n,m,N,dfn[maxn],low[maxn],st[maxn],top,cnt;
void dfs(int u,int last){
dfn[u] = low[u] = ++cnt;
st[++top] = u;
for (int k = hh[u],to; k; k = e[k].nxt){
if (k == last) continue;
if (!dfn[to = e[k].to]){
dfs(to,k ^ 1);
low[u] = min(low[u],low[to]);
if (low[to] >= dfn[u]){
++N;
do{add(st[top],N);}while (st[top--] != to);
add(N,u);
}
}
else low[u] = min(low[u],dfn[to]);
}
}
int K,a[maxn],fa[maxn][20],d[maxn][20],Dfn[maxn],dep[maxn],dfc;
void DFS(int u){
Dfn[u] = ++dfc; d[u][0] = (u <= n);
REP(i,19){
fa[u][i] = fa[fa[u][i - 1]][i - 1];
d[u][i] = d[u][i - 1] + d[fa[u][i - 1]][i - 1];
}
Redge(u) if ((to = ed[k].to) != fa[u][0]){
fa[to][0] = u; dep[to] = dep[u] + 1; DFS(to);
}
}
inline int lca(int u,int v){
if (dep[u] < dep[v]) swap(u,v);
for (int i = 0,D = dep[u] - dep[v]; (1 << i) <= D; i++)
if (D & (1 << i)) u = fa[u][i];
if (u == v) return u;
for (int i = 19; ~i; i--)
if (fa[u][i] != fa[v][i]){
u = fa[u][i];
v = fa[v][i];
}
return fa[u][0];
}
inline int getup(int u,int v){
if (u == v) return 0;
int re = -(u <= n);
for (int i = 19; ~i; i--)
if (fa[u][i] && dep[fa[u][i]] >= dep[v]){
re += d[u][i];
u = fa[u][i];
}
return re;
}
inline bool cmp(const int& a,const int& b){
return Dfn[a] < Dfn[b];
}
int pre[maxn];
void work(){
st[top = 1] = 1; int tot = 0,M = K;
sort(a + 1,a + 1 + K,cmp);
for (int i = 1; i <= K; i++){
int u = a[i],p = lca(u,st[top]);
if (u == 1) tot = INF;
if (p == st[top]) {if (u != st[top]) st[++top] = u;}
else {
while (true){
if (dep[p] >= dep[st[top - 1]]){
pre[st[top--]] = p; if (p == 1) tot++;
if (st[top] != p) st[++top] = p,a[++M] = p;
break;
}
pre[st[top]] = st[top - 1];
if (st[top - 1] == 1) tot++;
top--;
}
if (u != st[top]) st[++top] = u;
}
}
while (top > 1){
pre[st[top]] = st[top - 1];
if (st[top - 1] == 1) tot++;
top--;
}
if (tot < INF) a[++M] = 1;
int ans = 0;
for (int i = 1; i <= M; i++){
int u = a[i];
if (u == 1){
if (i > K && tot > 1) ans++;
continue;
}
if (pre[u] != 1 || (pre[u] == 1 && tot > 1)) ans += getup(u,pre[u]);
if (i > K) ans += (u <= n);
pre[u] = 0;
}
printf("%d\n",ans);
}
int main(){
int T = read();
while (T--){
cls(dfn); cls(h); cls(hh);
ne = Ne = 1; cnt = dfc = top = 0;
N = n = read(); m = read();
REP(i,m) build(read(),read());
dfs(1,0); DFS(1);
int q = read();
while (q--){
K = read();
REP(i,K) a[i] = read();
work();
}
}
return 0;
}
P4320
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 1000005,maxm = 100005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int h[maxn],ne = 1,hh[maxn],Ne = 1;
struct EDGE{int to,nxt;}ed[maxn << 2],e[maxn << 2];
inline void build(int u,int v){
e[++Ne] = (EDGE){v,hh[u]}; hh[u] = Ne;
e[++Ne] = (EDGE){u,hh[v]}; hh[v] = Ne;
}
inline void add(int u,int v){
ed[++ne] = (EDGE){v,h[u]}; h[u] = ne;
ed[++ne] = (EDGE){u,h[v]}; h[v] = ne;
}
int n,m,N,val[maxn];
int dfn[maxn],low[maxn],st[maxn],top,cnt;
void dfs(int u,int last){
dfn[u] = low[u] = ++cnt;
st[++top] = u;
for (int k = hh[u],to; k; k = e[k].nxt){
if (k == last) continue;
if (!dfn[to = e[k].to]){
dfs(to,k ^ 1);
low[u] = min(low[u],low[to]);
if (low[to] >= dfn[u]){
++N;
do{add(st[top],N);}while (st[top--] != to);
add(N,u);
}
}
else low[u] = min(low[u],dfn[to]);
}
}
int fa[maxn][20],d[maxn][20],Dfn[maxn],dep[maxn],dfc;
void DFS(int u){
Dfn[u] = ++dfc; d[u][0] = (u <= n);
REP(i,19){
fa[u][i] = fa[fa[u][i - 1]][i - 1];
d[u][i] = d[u][i - 1] + d[fa[u][i - 1]][i - 1];
}
Redge(u) if ((to = ed[k].to) != fa[u][0]){
fa[to][0] = u; dep[to] = dep[u] + 1; DFS(to);
}
}
int dis(int u,int v){
int re = 0;
if (dep[u] < dep[v]) swap(u,v);
for (int i = 0,D = dep[u] - dep[v]; (1 << i) <= D; i++)
if (D & (1 << i)){
re += d[u][i];
u = fa[u][i];
}
if (u == v) return re + 1;
for (int i = 19; ~i; i--)
if (fa[u][i] != fa[v][i]){
re += d[u][i] + d[v][i];
u = fa[u][i];
v = fa[v][i];
}
re += d[u][0] + d[v][0];
if (fa[u][0] <= n) re++;
return re;
}
int main(){
N = n = read(); m = read();
REP(i,m) build(read(),read());
dfs(1,0);
DFS(1);
int q = read(),u,v;
while (q--){
u = read(); v = read();
printf("%d\n",dis(u,v));
}
return 0;
}
洛谷P4606 [SDOI2018]战略游戏 【圆方树 + 虚树】的更多相关文章
- 洛谷P4606 [SDOI2018]战略游戏 [广义圆方树]
传送门 思路 先考虑两点如何使他们不连通. 显然路径上所有的割点都满足条件. 多个点呢?也是这样的. 于是可以想到圆方树.一个点集的答案就是它的虚树里圆点个数减去点集大小. 可以把点按dfs序排序,然 ...
- Luogu P4606 [SDOI2018] 战略游戏 圆方树 虚树
https://www.luogu.org/problemnew/show/P4606 把原来的图的点双联通分量缩点(每个双联通分量建一个点,每个割点再建一个点)(用符合逻辑的方式)建一棵树(我最开始 ...
- bzoj5315/luoguP4517 [SDOI2018]战略游戏(圆方树,虚树)
bzoj5315/luoguP4517 [SDOI2018]战略游戏(圆方树,虚树) bzoj Luogu 题目描述略(太长了) 题解时间 切掉一个点,连通性变化. 上圆方树. $ \sum |S| ...
- [SDOI2018]战略游戏 圆方树,树链剖分
[SDOI2018]战略游戏 这题是道路相遇(题解)的升级版,询问的两个点变成了\(S\)个点. LG传送门 还是先建出圆方树,考虑对于询问的\(S\)个点,答案就是圆方树上能包含这些点的最小连通块中 ...
- 洛谷4606 SDOI2018战略游戏(圆方树+虚树)
QWQ深受其害 当时在现场是真的绝望...... 现在再重新来看这个题 QWQ 根据题目所说,我们可以发现,对于每一个集合中的节点,我们实际上就是要求两两路径上的割点的数目 考虑到又是关于点双的题目, ...
- BZOJ5329:[SDOI2018]战略游戏(圆方树,虚树)
Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着 ...
- Luogu4606 SDOI2018 战略游戏 圆方树、虚树、链并
传送门 弱化版 考虑到去掉一个点使得存在两个点不连通的形式类似割点,不难想到建立圆方树.那么在圆方树上对于给出的关键点建立虚树之后,我们需要求的就是虚树路径上所有圆点的数量减去关键点的数量. 因为没有 ...
- BZOJ.5329.[SDOI2018]战略游戏(圆方树 虚树)
题目链接 显然先建圆方树,方点权值为0圆点权值为1,两点间的答案就是路径权值和减去起点终点. 对于询问,显然可以建虚树.但是只需要计算两关键点间路径权值,所以不需要建出虚树.统计DFS序相邻的两关键点 ...
- Solution -「SDOI 2018」「洛谷 P4606」战略游戏
\(\mathcal{Description}\) Link. 给定一个 \(n\) 个点 \(m\) 条边的无向连通图,\(q\) 次询问,每次给出一个点集 \(s\),求至少在原图中删去多 ...
随机推荐
- 创建Springmvc项目时,特殊拦截器失效情况的原因及解决办法
最近开发一个新项目时,搭建springmvc框架时,遇到一个拦截器失效的情况困扰了两天.现在解决,特此记录一下. 拦截器不生效的情况描述: 设置登录拦截的时候,首先登录接口肯定是不用拦截的.所以需要在 ...
- Javascript库,前端框架(UI框架),模板引擎
JavaScript库:JQuery,undoscore,Zepto 纯Javascript语言封装, 前端框架(UI框架):Bootstrap,Foundation,Semantic UI,Pure ...
- js中对象转化成字符串、数字或布尔值的转化规则
js中对象可以转化成 字符串.数字.布尔值 一.对象转化成字符串: 规则: 1.如果对象有toString方法,则调用该方法,并返回相应的结果:(代码通常会执行到这,因为在所有对象中都有toStrin ...
- 亚马逊CEO贝索斯致股东信:阐述公司未来计划
亚马逊CEO 杰夫·贝索斯(Jeff Bezos)今天发布年度股东信, 详细描述了亚马逊的产品.服务和未来计划,当然,信中并没有任何的硬数据,比如说亚马逊Kindle的销量等等.但这封信也包括一些颇令 ...
- php命名空间学习笔记。
为什么要用命名空间? 在PHP中,命名空间用来解决在编写类库或应用程序时创建可重用的代码如类或函数时碰到的两类问题: 用户编写的代码 与 PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲 ...
- C++寒假计划
课程 西北工业大学的c++程序设计 理由 这个课程里的内容都比较详细,能比较全面的讲解C++,我们是从C过渡到C++的,所以我之前看了阚道洪的面向对象程序设计的课程,他讲解了两者的差别,还有C++对C ...
- 2016-2017 ACM-ICPC, NEERC, Moscow Subregional Contest Problem L. Lazy Coordinator
题目来源:http://codeforces.com/group/aUVPeyEnI2/contest/229511 时间限制:1s 空间限制:512MB 题目大意: 给定一个n 随后跟着2n行输入 ...
- C++总结作业
在博客作业中学到的内容 在博客作业中,首先我学到了Markdown编辑器的排版格式,github的上传,如果没有博客作业,可能根本不会接触到这些内容.然后,就C++来讲,我在博客作业中学会了命令行参数 ...
- 软工实践-Alpha 冲刺 (8/10)
队名:起床一起肝活队 组长博客:博客链接 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去两天完成了哪些任务 描述: 已经解决登录注册等基本功能的界面. 完成非功能的主界面制作 ...
- HDU 5195 DZY Loves Topological Sorting 拓扑排序
题目链接: hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5195 bc(中文):http://bestcoder.hdu.edu.cn/contests ...