Bear and Chemistry[CF639F]

链接

CF

题解

用来练码力的题。

这种题还写了1.5h真的差评。

显然你先直接缩点,变成一个森林。

然后每次询问就是给你一些点和边,表示在森林的基础上再加上这些边,然后跑边双,问这些点是否在同一个边双内。

那么在森林上对这些点建出虚树,然后再跑Tarjan就好了。

时间复杂度 $O((n+m)\log n)$。

有那么亿点细节。。

程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#include <bits/stdc++.h>
using namespace std;
#define FO(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
#define fo(i,j,k) for(int i=(j),end_i=(k);i<=end_i;i++)
#define ff(i,j,k) for(int i=(j),end_i=(k);i< end_i;i++)
#define fd(i,j,k) for(int i=(j),end_i=(k);i>=end_i;i--)
#define DEBUG(x) cerr<<#x<<"="<<x<<endl
#define all(x) (x).begin(),(x).end()
#define cle(x) memset(x,0,sizeof(x))
#define lowbit(x) ((x)&-(x))
#define ll long long
#define ull unsigned ll
#define db double
#define lb long db
#define pb push_back
#define mp make_pair
#define fi first
#define se second
inline int read()
{
int x=0; char ch=getchar(); bool f=0;
for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') f=1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+(ch^48);
return f?-x:x;
}
#define CASET fo(___,1,read())
const int N=6e5+5;
int n,col[N],bel[N],m,q,cnt;
struct edge{
int x,y;
};
namespace Graph{
int dfn[N],low[N],tim;
int ver[N],ne[N],head[N],tot;
bool vis[N];
vector<int> bridge;
inline void add(int x,int y)
{
ver[++tot]=y; ne[tot]=head[x]; head[x]=tot;
ver[++tot]=x; ne[tot]=head[y]; head[y]=tot;
}
void dfs(int u,int pre)
{
dfn[u]=low[u]=++tim;
bool flag=0;
for(int i=head[u],v;i;i=ne[i])
if(!dfn[v=ver[i]])
{
dfs(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u]) vis[i]=vis[i^1]=1,bridge.pb(i);
}
else
{
if(v!=pre) low[u]=min(low[u],dfn[v]);
else
if(!flag) flag=1;
else low[u]=min(low[u],dfn[v]);
}
}
void dfs(int u)
{
col[u]=cnt;
for(int i=head[u],v;i;i=ne[i])
if(!col[v=ver[i]]&&!vis[i])
dfs(v);
}
inline void work(vector<int> &a,vector<edge> &E)
{
tim=0; tot=1; cnt=0;
for(int i:bridge) vis[i]=vis[i^1]=0;
bridge.clear();
for(int i:a) head[i]=dfn[i]=low[i]=col[i]=0;
for(edge v:E) add(v.x,v.y);
for(int i:a) if(!dfn[i]) dfs(i,0);
for(int i:a) if(!col[i]) ++cnt,dfs(i);
}
}
using Graph::ver;

vector<edge> E,E1;
vector<int> V,V1,V2;
namespace Tree{
vector<int> adj[N];
int dep[N],f[N][20],rt[N],dfn[N],tim;
inline void add(int x,int y)
{
adj[x].pb(y); adj[y].pb(x);
}
void dfs(int u,int pre)
{
dfn[u]=++tim; f[u][0]=pre;
dep[u]=dep[pre]+1;
fo(i,1,19) f[u][i]=f[f[u][i-1]][i-1];
for(int v:adj[u]) if(v!=pre) rt[v]=rt[u],dfs(v,u);
}
void work()
{
for(int i:Graph::bridge) add(col[ver[i]],col[ver[i^1]]);
fo(i,1,cnt) if(!dep[i]) rt[i]=i,dfs(i,0);
}
inline int lca(int x,int y)
{
if(dep[x]>dep[y]) swap(x,y);
fd(i,19,0) if(f[y][i]&&dep[f[y][i]]>=dep[x]) y=f[y][i];
if(x==y) return x;
fd(i,19,0) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
return f[x][0];
}
void build(vector<int> &a)
{
sort(all(a),[&](const int &x,const int &y){return dfn[x]<dfn[y];});
a.resize(unique(all(a))-a.begin());
static int st[N],top,now;
top=now=0;
int y;
for(int x:a)
{
if(top&&rt[x]!=now)
for(;--top;) E1.pb((edge){st[top],st[top+1]});
else if(top)
{
y=lca(x,st[top]);
if(y!=st[top])
{
for(;top>=2&&dep[st[top-1]]>=dep[y];top--) E1.pb((edge){st[top],st[top-1]});
if(st[top]!=y) E1.pb((edge){st[top],y}),st[top]=y,V1.pb(y);
}
}
now=rt[x];
if(st[top]!=x) st[++top]=x;
}
if(top) for(;--top;) E1.pb((edge){st[top],st[top+1]});
}
}

inline bool check()
{
for(edge i:E) V2.pb(i.x),V2.pb(i.y);
for(int i:V) V2.pb(i);
Tree::build(V2);
for(edge i:E) E1.pb((edge){i.x,i.y});
for(int i:V2) V1.pb(i);
sort(all(V1));
V1.resize(unique(all(V1))-V1.begin());
Graph::work(V1,E1);
int c=col[V[0]];
ff(i,1,V.size()) if(col[V[i]]!=c) return 0;
return 1;
}

int Rnow;
inline int change(int x)
{
x=(x+Rnow)%n;
if(x) return x;
return n;
}
int main()
{
n=read(); m=read(); q=read();
fo(i,1,m) E.pb((edge){read(),read()});
fo(i,1,n) V.pb(i);
Graph::work(V,E);
fo(i,1,n) bel[i]=col[i];
Tree::work();
for(int T=1,v,e;T<=q;T++)
{
v=read(); e=read();
E.clear(); V.clear();
E1.clear(); V1.clear(); V2.clear();
fo(i,1,v) V.pb(bel[change(read())]);
fo(i,1,e) E.pb((edge){bel[change(read())],bel[change(read())]});
if(check()) puts("YES"),Rnow=(Rnow+T)%n;
else puts("NO");
}
return 0;
}