题目大意:

  给一个$G=(V,E)$,满足$|V|=n$,$|E|=m$,且保证图联通,有Q个询问,每组询问有s个点,求图中有多少点满足:将其删去后,这s个点中存在一对点集$(a,b)$不联通且删去点不为s中的点。

  $n,m,\sum s$均为$1e5$级别。

题解:

  显然满足性质的点都是割点。

  我们建一颗圆方树,然后考虑对于每组询问为所有点之间路径覆盖的割点数量。

  用虚树+树剖维护即可。

  不是很难,但考场上把点双写错,多调了1h。

代码:

#include "bits/stdc++.h"

using namespace std;

inline int read() {
int s=0,k=1;char ch=getchar();
while (ch<'0'|ch>'9') ch=='-'?k=-1:0,ch=getchar();
while (ch>47&ch<='9') s=s*10+(ch^48),ch=getchar();
return s*k;
} const int N=2e5+10; struct edges {
int v;edges *last;
}; int n,m; int low[N],dfn[N],stk[N],bcc_cnt,top,idx,rt,son,cut[N],bel[N],pos[N];
vector<int> bcc[N]; int ga[N],fat[N],rid[N],size[N],heavy[N],tid[N],dfx,ncut[N],deep[N]; struct Group{
inline void Clear(){ecnt=edge;memset(head,0,sizeof head);}
edges edge[N<<2],*head[N],*ecnt; inline void push(int u,int v){
*ecnt=(edges){v,head[u]},head[u]=ecnt++;
*ecnt=(edges){u,head[v]},head[v]=ecnt++;
} inline void tarjan(int x,int fa) {
low[x]=dfn[x]=++idx;
for (edges *i=head[x];i;i=i->last) if ((fa^1)!=i-edge){
if (!dfn[i->v]) {
if (x==rt) ++son;
stk[++top] = i-edge;
tarjan(i->v,i-edge);
if (low[i->v]>=dfn[x]) {
int t=0;bcc_cnt++;
bcc[bcc_cnt].clear();
do {
t=stk[top--];
bcc[bcc_cnt].push_back(edge[t].v);
}while (t!=i-edge);
bcc[bcc_cnt].push_back(x);
cut[x]=true;
} else low[x]=min(low[i->v],low[x]);
} else if (dfn[i->v]<low[x]){
low[x] = dfn[i->v];
}
}
} inline void tarjan(){
rt=1;son=0;
tarjan(1,-1); if (son>1) cut[1]=true;
else cut[1]=false;
} inline void dfs(int x,int fa) {
size[x]=1;
for (edges *i=head[x];i;i=i->last) if (i->v!=fa) {
deep[i->v]=deep[x]+1;
dfs(i->v,x);
fat[i->v]=x;
size[x]+=size[i->v];
if (size[i->v]>size[heavy[x]])
heavy[x]=i->v;
}
} inline void dfs(int x,int fa,int grand) {
ga[x]=grand;
tid[x]=++dfx;
rid[dfx]=x;
if (heavy[x]) {
dfs(heavy[x],x,grand);
for (edges *i=head[x];i;i=i->last) if (i->v!=fa&&i->v!=heavy[x])
dfs(i->v,x,i->v);
}
} inline void dfs() {
dfs(1,0);
dfs(1,0,1);
}
}g[2]; struct node {
node (){lc=rc=NULL,val=0;}
node *lc,*rc;
int val;
}tree[N*40],*tcnt=tree,*fina,*root; inline void update(node *u) {
u->val=u->lc->val+u->rc->val;
} inline void build (node *&u,int l,int r) {
u=tcnt++;
*u=node();
if (l==r) {
u->val=ncut[rid[l]];
return ;
}
int mid=l+r>>1;
build(u->lc,l,mid);
build(u->rc,mid+1,r);
update(u);
} inline void update(node *&u,int l,int r,int x,int y) {
if (u<fina) {
node *t=tcnt++;
*t=*u;
u=t;
}
if (x<=l&&r<=y) {u->val=0;return ;}
int mid=l+r>>1;
if (y>mid) update(u->rc,mid+1,r,x,y);
if (x<=mid) update(u->lc,l,mid,x,y);
update(u);
} inline int query(node *u,int l,int r,int x,int y) {
if (!u->val) return 0;
if (x<=l&&r<=y) return u->val;
int mid=l+r>>1,ret=0;
if (y>mid) ret+=query(u->rc,mid+1,r,x,y);
if (x<=mid) ret+=query(u->lc,l,mid,x,y);
return ret;
} inline int cmp(int x,int y) {
return tid[x]<tid[y];
} inline int lca(int x,int y) {
while (ga[x]!=ga[y]) {
if (deep[ga[x]]<deep[ga[y]])
swap(x,y);
x=fat[ga[x]];
}
if (deep[x]<deep[y]) return x;
return y;
} inline int query(int x,int y) {
int ret=0;
while (ga[x]!=ga[y]) {
if (deep[ga[x]]<deep[ga[y]])
swap(x,y);
ret+=query(root,1,m,tid[ga[x]],tid[x]);
update(root,1,m,tid[ga[x]],tid[x]);
x=fat[ga[x]];
}
if (deep[x]>deep[y]) swap(x,y);
if (tid[x]<=tid[y])
ret+=query(root,1,m,tid[x],tid[y]),
update(root,1,m,tid[x],tid[y]);
return ret;
} int main (int argc, char const* argv[]){
int T=read();
while (T--){
memset(g,0,sizeof g);
g[0].Clear();
g[1].Clear();
memset(cut,0,sizeof cut);
memset(ncut,0,sizeof ncut);
memset(dfn,0,sizeof dfn);
memset(heavy,0,sizeof heavy);
tcnt=tree;
bcc_cnt=0;
dfx=0,idx=0;
n=read(),m=read();
register int i,j;
for (i=1;i<=m;++i) {
int x=read(),y=read();
g[0].push(x,y);
}
g[0].tarjan();
int s=bcc_cnt;
for (i=1;i<=n;++i)
if (cut[i])
++s,cut[i]=s,ncut[cut[i]]=1;
for (i=1;i<=bcc_cnt;++i) {
for (j=0;j<bcc[i].size();++j)
if (cut[bcc[i][j]])
g[1].push(i,cut[bcc[i][j]]);
else bel[bcc[i][j]]=i;
}
g[1].dfs();
build(root,1,s);
m=s;
fina=tcnt;
int Q=read(),tmp;
int ans=0;
while (Q--) {
root=tree;
tcnt=fina;
s=read();
for (i=1;i<=s;++i) {
pos[i]=read();
if (cut[pos[i]]) pos[i]=cut[pos[i]],update(root,1,m,tid[pos[i]],tid[pos[i]]);
else pos[i]=bel[pos[i]];
}
sort(pos+1,pos+s+1,cmp);
tmp=pos[1];
ans=0;
for (i=2;i<=s;++i) {
ans+=query(tmp,pos[i]); }
printf("%d\n",ans);
}
}
return 0;
}

  

「SDOI 2018」战略游戏的更多相关文章

  1. Solution -「SDOI 2018」「洛谷 P4606」战略游戏

    \(\mathcal{Description}\)   Link.   给定一个 \(n\) 个点 \(m\) 条边的无向连通图,\(q\) 次询问,每次给出一个点集 \(s\),求至少在原图中删去多 ...

  2. 「SDOI 2018」反回文串

    题目大意: 求字符集大小为$k$长度为$n$的经循环移位后为回文串的数量. 题解: 这题是D1里最神的吧 考虑一个长度为$n$回文串,将其循环移位后所有的串都是满足要求的串. 但是显然这样计算会算重. ...

  3. 「TJOI 2018」教科书般的亵渎

    「TJOI 2018」教科书般的亵渎 题目描述 小豆喜欢玩游戏,现在他在玩一个游戏遇到这样的场面,每个怪的血量为 \(a_i\) ,且每个怪物血量均不相同, 小豆手里有无限张"亵渎" ...

  4. LOJ #2542. 「PKUWC 2018」随机游走(最值反演 + 树上期望dp + FMT)

    写在这道题前面 : 网上的一些题解都不讲那个系数是怎么推得真的不良心 TAT (不是每个人都有那么厉害啊 , 我好菜啊) 而且 LOJ 过的代码千篇一律 ... 那个系数根本看不出来是什么啊 TAT ...

  5. Loj #2494. 「AHOI / HNOI2018」寻宝游戏

    Loj #2494. 「AHOI / HNOI2018」寻宝游戏 题目描述 某大学每年都会有一次 Mystery Hunt 的活动,玩家需要根据设置的线索解谜,找到宝藏的位置,前一年获胜的队伍可以获得 ...

  6. LOJ #2802. 「CCC 2018」平衡树(整除分块 + dp)

    题面 LOJ #2802. 「CCC 2018」平衡树 题面有点难看...请认真阅读理解题意. 转化后就是,给你一个数 \(N\) ,每次选择一个 \(k \in [2, N]\) 将 \(N\) 变 ...

  7. LOJ #2541. 「PKUWC 2018」猎人杀(容斥 , 期望dp , NTT优化)

    题意 LOJ #2541. 「PKUWC 2018」猎人杀 题解 一道及其巧妙的题 , 参考了一下这位大佬的博客 ... 令 \(\displaystyle A = \sum_{i=1}^{n} w_ ...

  8. LOJ #2540. 「PKUWC 2018」随机算法(概率dp)

    题意 LOJ #2540. 「PKUWC 2018」随机算法 题解 朴素的就是 \(O(n3^n)\) dp 写了一下有 \(50pts\) ... 大概就是每个点有三个状态 , 考虑了但不在独立集中 ...

  9. LOJ #2538. 「PKUWC 2018」Slay the Spire (期望dp)

    Update on 1.5 学了 zhou888 的写法,真是又短又快. 并且空间是 \(O(n)\) 的,速度十分优秀. 题意 LOJ #2538. 「PKUWC 2018」Slay the Spi ...

随机推荐

  1. Jmeter(二十五)_Xpath关联

    在Jmeter中,除了正则表达式可以用作关联,还有一种方式也可以做关联,那就是 XPath Extractor.它是利用xpath提取出关键信息,传递变量. 具体用法 添加一个后置处理器-XPath ...

  2. Spring Cloud入门教程-Hystrix断路器实现容错和降级

    简介 Spring cloud提供了Hystrix容错库用以在服务不可用时,对配置了断路器的方法实行降级策略,临时调用备用方法.这篇文章将创建一个产品微服务,注册到eureka服务注册中心,然后我们使 ...

  3. WEB 集群与负载均衡(一)基本概念-上

    Web集群是由多个同时运行同一个web应用的服务器组成,在外界看来就像一个服务器一样,这多台服务器共同来为客户提供更高性能的服务.集群更标准的定义是:一组相互独立的服务器在网络中表现为单一的系统,并以 ...

  4. 发布开源库到JCenter所遇到的一些问题记录

    这周末自己瞎折磨了下,如何发布开源库到 JCenter,然后这过程中碰到了一些问题,在此记录分享一下 本篇是基于上一篇:教你一步步发布一个开源库到 JCenter 介绍的流程.步骤中所遇到的问题,所以 ...

  5. DUEditor的诞生

    书接上回线上项目py2升级py3的事,除了上篇blog说到的snspy,主要升级的一个包就是DjangoUeditor,由于这个项目的维护人也不维护了,最后所幸自己开了支持Py3且加了一定优化的新版本 ...

  6. Android Studio 2.3 instant run与miui冲突问题的解决

    Android Studio最近发布的2.3版本,由于这个版本改进后的Instant Run功能和很多国内ROM存在兼容问题,所以导致不得不做一些妥协策略,具体在小米Rom上,就是把小米rom的调试定 ...

  7. unity零基础开始学习做游戏(四)biu~biu~biu发射子弹打飞机

    -------小基原创,转载请给我一个面子 主角都能移动了,那不得做点什么伸张正义,守护世界和平的事嘛,拿起家伙biu~biu~biu~ 首先得做一个好人和一个坏人 老规矩,Canvas下创建两个Im ...

  8. github routine

    1. 从官方库fork 自己的分支库后,git clone到local. 2. local的remotes/origin默认是自己的分支库.可以添加remotes/upstream指向官方库. 3. ...

  9. crontab定时任务, 定时到秒

    crontab定时任务最小支持到minute, 定时到秒执行的任务, 写起来比较麻烦 * * * * * /bin/sh /home/jiewang/portraitProc/test.sh > ...

  10. goroutine和线程区别

    从调度上看,goroutine的调度开销远远小于线程调度开销. OS的线程由OS内核调度,每隔几毫秒,一个硬件时钟中断发到CPU,CPU调用一个调度器内核函数.这个函数暂停当前正在运行的线程,把他的寄 ...