这道题就是缩缩缩!
先把原图缩成一个双连通树 然后查询的时候把所有关键点缩成一颗虚树 加完询问里的边 在缩一次双连通
这里缩虚树的时候LCA用欧拉序列做 怕倍增太慢
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<stack>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const int N=300005;
struct edge{
int u,v,next;
}G[N*20];
int head1[N],head2[N],head3[N],inum=1;
int *head;
int tag[N<<1];
inline void add(int u,int v,int p,int *head=::head){
G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;
}
int bcc[N],tot;
int clk,pre[N],low[N];
stack<int> S;
#define U G[p].u
#define V G[p].v
inline void Tarjan(int u,int fa){
pre[u]=low[u]=++clk; S.push(u);
for (int p=head[u];p;p=G[p].next){
if (p==(fa^1)) continue;
if (!pre[V]){
Tarjan(V,p);
low[u]=min(low[u],low[V]);
if (low[V]>pre[u]){
++tot;
while (S.top()!=V)
bcc[S.top()]=tot,S.pop();
bcc[S.top()]=tot,S.pop();
tag[p]=1;
}
}else
low[u]=min(low[u],pre[V]);
}
}
int eular[N<<2],back[N];
int tid[N],depth[N];
namespace ST{
inline int Min(int a,int b){
return depth[a]<depth[b]?a:b;
}
const int K=25;
int Log[N<<2];
int st[N<<2][K];
inline void Pre(int n,int *a){
for (int i=2;i<=n;i++) Log[i]=Log[i>>1]+1;
for (int i=1;i<=n;i++) st[i][0]=a[i];
for (int k=1;k<=Log[n];k++)
for (int i=1;i<=n;i++){
st[i][k]=st[i][k-1];
if (i+(1<<(k-1))<=n)
st[i][k]=Min(st[i][k],st[i+(1<<(k-1))][k-1]);
}
}
inline int Query(int l,int r){
if (l>r) swap(l,r);
int t=Log[r-l+1];
return Min(st[l][t],st[r-(1<<t)+1][t]);
}
}
int root[N],troot;
inline void dfs(int u,int fa){
root[u]=troot;
tid[u]=++clk; eular[++*eular]=u; back[u]=*eular; depth[u]=depth[fa]+1;
for (int p=head[u];p;p=G[p].next)
if (V!=fa)
dfs(V,u),eular[++*eular]=u;
}
inline int LCA(int u,int v){
return ST::Query(back[u],back[v]);
}
int n,m,Q;
int in,im;
int ps[N],us[N],vs[N];
int lst[N<<2],pnt;
bool cmp(int a,int b){
return tid[a]<tid[b];
}
int Stack[N<<2],top;
int ibcc[N],itot;
int iclk,ipre[N],ilow[N];
inline void iTarjan(int u,int fa){
ipre[u]=ilow[u]=++iclk; S.push(u);
for (int p=head[u];p;p=G[p].next){
if (p==(fa^1)) continue;
if (!ipre[V]){
iTarjan(V,p);
ilow[u]=min(ilow[u],ilow[V]);
if (ilow[V]>ipre[u]){
++itot;
while (S.top()!=V)
ibcc[S.top()]=itot,S.pop();
ibcc[S.top()]=itot,S.pop();
}
}else
ilow[u]=min(ilow[u],ipre[V]);
}
}
int main(){
int iu,iv; int R=0;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); read(m); read(Q); head=head1;
for (int i=1;i<=m;i++)
read(iu),read(iv),add(iu,iv,++inum),add(iv,iu,++inum);
for (int i=1;i<=n;i++)
if (!pre[i]){
Tarjan(i,0);
if (!S.empty()){
++tot;
while (!S.empty())
bcc[S.top()]=tot,S.pop();
}
}
int tmp=inum;
for (int p=2;p<=tmp;p++)
if (tag[p])
add(bcc[U],bcc[V],++inum,head2),add(bcc[V],bcc[U],++inum,head2);
head=head2;
clk=0;
for (int i=1;i<=tot;i++)
if (!tid[i])
troot=i,dfs(i,0);
ST::Pre(*eular,eular);
tmp=inum;
head=head3;
for (int T=1;T<=Q;T++){
read(in); read(im); pnt=0;
for (int i=1;i<=in;i++){
read(ps[i]); ps[i]=(ps[i]+R-1)%n+1,ps[i]=bcc[ps[i]];
lst[++pnt]=ps[i];
}
for (int i=1;i<=im;i++){
read(us[i]),read(vs[i]); us[i]=(us[i]+R-1)%n+1,vs[i]=(vs[i]+R-1)%n+1;
us[i]=bcc[us[i]],vs[i]=bcc[vs[i]],lst[++pnt]=us[i],lst[++pnt]=vs[i];
}
sort(lst+1,lst+pnt+1,cmp);
pnt=unique(lst+1,lst+pnt+1)-lst-1;
for (int l=1,r;l<=pnt;l=r+1){
r=l; while (r<pnt && root[lst[r+1]]==root[lst[r]]) r++;
top=0; Stack[++top]=root[lst[l]];
for (int i=l;i<=r;i++){
int now=lst[i],lca=LCA(now,Stack[top]);
while(1){
if(depth[lca]>=depth[Stack[top-1]]){
add(lca,Stack[top],++inum),add(Stack[top],lca,++inum);
top--;
if (Stack[top]!=lca) Stack[++top]=lca;
break;
}
add(Stack[top-1],Stack[top],++inum); add(Stack[top],Stack[top-1],++inum); top--;
}
if (Stack[top]!=now) Stack[++top]=now;
}
while (--top) add(Stack[top],Stack[top+1],++inum),add(Stack[top+1],Stack[top],++inum);
}
for (int i=1;i<=im;i++)
add(us[i],vs[i],++inum),add(vs[i],us[i],++inum);
for (int i=1;i<=pnt;i++)
if (!ipre[lst[i]]){
iTarjan(lst[i],0);
if (!S.empty()){
++itot;
while (!S.empty())
ibcc[S.top()]=itot,S.pop();
}
}
int flag=1;
for (int i=2;i<=in && flag;i++)
if (ibcc[ps[i]]!=ibcc[ps[1]])
flag=0;
flag?((R+=T)%=n,printf("YES\n")):printf("NO\n");
for (int p=tmp+1;p<=inum;p++)
head3[U]=ipre[U]=ilow[U]=ibcc[U]=0,head3[V]=ipre[V]=ilow[V]=ibcc[V]=0;
inum=tmp; iclk=0; itot=0;
}
return 0;
}