题目大意:

一个无向图 Q个询问 每次给一些点的集合

求有多少个点满足去掉这个点后使这些点的集合中有一个点对不连通

思路:

点双缩点 相当于每次求这些点中的所有路径上的圆点个数

可以将这些点按dfs序排序 每次求a i 和 a i+1两个点路径上的圆点个数

最后答案/2 后减去这些点的个数(因为不能取这些点) 再判断 a i 和a n的lca是否是圆点

 #include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define inf 2139062143
#define ll long long
#define MAXN 400100
#define V1 (g1.to[i])
#define V2 (g2.to[i])
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-;ch=getchar();}
while(isdigit(ch)) {x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,m;
int dfn[MAXN],st[MAXN],low[MAXN],top,stp;
int f[MAXN][],dep[MAXN],dis[MAXN];
struct graph
{
int fst[MAXN],nxt[MAXN<<],to[MAXN<<],cnt;
void mem(){memset(fst,,sizeof(fst));cnt=;}
void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;}
}g1,g2;
void tarjan(int x)
{
dfn[x]=low[x]=++stp,st[++top]=x;int now=;
for(int i=g1.fst[x];i;i=g1.nxt[i])
if(!dfn[V1])
{
tarjan(V1);low[x]=min(low[x],low[V1]);
if(low[V1]<dfn[x]) continue;m++;
do{now=st[top--];g2.add(m,now);}
while(now!=V1);g2.add(x,m);
}
else low[x]=min(low[x],dfn[V1]);
}
void dfs(int x)
{
dfn[x]=++stp;
for(int i=;(<<i)<=dep[x];i++) f[x][i]=f[f[x][i-]][i-];
for(int i=g2.fst[x];i;i=g2.nxt[i])
{f[V2][]=x,dep[V2]=dep[x]+,dis[V2]=dis[x]+(V2<=n);dfs(V2);}
}
int lca(int a,int b)
{
if(dep[a]<dep[b]) swap(a,b);
int t=dep[a]-dep[b];
for(int i=;i>=;i--) if((<<i)&t) a=f[a][i];
if(a==b) return a;
for(int i=;i>=;i--) if(f[a][i]!=f[b][i]) a=f[a][i],b=f[b][i];
return f[a][];
}
bool cmp(const int &a,const int &b) {return dfn[a]<dfn[b];}
inline int calc(int a,int b) {return dis[a]+dis[b]-(dis[lca(a,b)]<<);}
int main()
{
int T=read(),a,b,k,q,res;
while(T--)
{
g1.mem();g2.mem();memset(dfn,,sizeof(dfn));
memset(f,,sizeof(f));
n=read(),m=read(),stp=top=;
while(m--) {a=read(),b=read();g1.add(a,b);g1.add(b,a);}
m=n;tarjan();dis[]=dep[]=,stp=;dfs();
q=read();
while(q--)
{
k=read(),top=,res=;
while(k--) st[++top]=read();
sort(st+,st+top+,cmp);
for(int i=;i<=top;i++)
res+=calc(st[i],st[i%top+]);
if(lca(st[],st[top])<=n) printf("%d\n",(res+-top*)>>);
else printf("%d\n",(res-top*)>>);
}
}
}

最新文章

  1. MongoDB学习笔记~为IMongoRepository接口添加了增删改方法,针对官方驱动
  2. JavaScript获取图片的原始尺寸
  3. 《MySchool数据库设计优化》内部测试
  4. mysql-5.7.10-winx64 安装时遇到的问题
  5. 51nod1240莫比乌斯函数
  6. MYSQL 为表指定文件位置 data directory
  7. unity插件开发——MenuItem
  8. Bundle使用&amp;NSBundle
  9. css清除默认样式,stylus学习
  10. renameTo()判断文件是否被占用(判断大文件是否完成拷贝这个动作)
  11. grid和flex区别
  12. MATLAB用二分法、不动点迭代法及Newton迭代(切线)法求非线性方程的根
  13. HTTP1.0、HTTP1.1和HTTP2.0的区别
  14. pom.xml实例
  15. npm node sass 安装报错
  16. Math对象的属性和方法
  17. 转 proc文件
  18. 开启Unity项目中VS工程的属性面板
  19. Collection与Collections、ArrayList和Vector、HashMap和Hashtable(面试常用)
  20. OpenCV漫水填充算法示例代码

热门文章

  1. 用SQLLDR来装载date类型的控制文件
  2. windows环境下SVN服务器限制注释字数
  3. 【2018 Multi-University Training Contest 5】
  4. BZOJ1739: [Usaco2005 mar]Space Elevator 太空电梯
  5. UVA 861 组合数学 递推
  6. controller跳到另一个controller
  7. js删除数组对象中符合条件的数据
  8. P1093||T1142 奖学金 洛谷||codevs
  9. 2017CodeM初赛A场
  10. 【转】PHP实现系统编程(四)--- 本地套接字(Unix Domain Socket)