BZOJ3569:DZY Loves Chinese II(线性基)_线性基

Description

神校XJ学霸兮,Dzy皇考曰JC
摄提贞于孟陬兮,惟庚寅Dzy以降。
Dzy既有此内美兮,又重之以修能。
遂降临于OI界,欲以神力而凌辱众生。
 
Dzy有一魞歄图,其上有N座祭坛,又有M条膴蠁边。
时而DzyWA而怒发冲冠,神力外溢,遂有K条膴蠁边灰飞烟灭。
而后俟其日A50题则又令其复原。(可视为立即复原)
然若有祭坛无法相互到达,Dzy之神力便会大减,于是欲知其是否连通。

Input

第一行N,M
接下来Mx,y:表示M条膴蠁边,依次编号
接下来一行Q
接下来Q行:
每行第一个数K而后K个编号c1~cK:表示K条边,编号为c1~cK
为了体现在线,c1~cK均需异或之前回答为连通的个数

Output

对于每个询问输出:连通则为‘Connected’,不连通则为‘Disconnected
(不加引号)

Sample Input

5 10
2 1
3 2
4 2
5 1
5 3
4 1
4 3
5 2
3 1
5 4
5
1 1
3 7 0 3
4 0 7 4 6
2 2 7
4 5 0 2 13

Sample Output

Connected
Connected
Connected
Connected
Disconnected

HINT

N≤100000 M≤500000 Q≤50000 1≤K≤15
数据保证没有重边与自环
Tip:请学会使用搜索引擎

Solution

这个随机做法很巧妙啊……

首先我们$DFS$出一棵树,对于非树边赋随机值,树边为所有在树上覆盖它的非树边的异或和。

可以发现,对于给定边集,如果有子集异或和为$0$,那么图就被砍成不连通的了。

因为对于一条树边,如果想砍它让图不连通,就必须砍掉其他所有覆盖它的非树边。

所以每次询问用线性基维护一下就好了。

Code

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 #define N (100009)
 6 #define M (500009)
 7 #define MOD (1000000007)
 8 using namespace std;
 9 
10 struct Edge{int to,next;}edge[M<<1];
11 int n,m,q,k,ans,val[M],XOR[N],DFN[N],d[32],dfs_num;
12 int head[N],num_edge;
13 
14 inline int read()
15 {
16     int x=0,w=1; char c=getchar();
17     while (c<'0' || c>'9') {if (c=='-') w=-1; c=getchar();}
18     while (c>='0' && c<='9') x=x*10+c-'0', c=getchar();
19     return x*w;
20 }
21 
22 void add(int u,int v)
23 {
24     edge[++num_edge].to=v;
25     edge[num_edge].next=head[u];
26     head[u]=num_edge;
27 }
28 
29 void DFS(int x,int fa)
30 {
31     DFN[x]=++dfs_num;
32     for (int i=head[x]; i; i=edge[i].next)
33         if (!DFN[edge[i].to])
34         {
35             DFS(edge[i].to,x);
36             val[(i+1)>>1]=XOR[edge[i].to];
37             XOR[x]^=XOR[edge[i].to];
38         }
39         else if (DFN[edge[i].to]<DFN[x] && edge[i].to!=fa)
40         {
41             val[(i+1)>>1]=rand();
42             XOR[x]^=val[(i+1)>>1];
43             XOR[edge[i].to]^=val[(i+1)>>1];
44         }
45 }
46 
47 int main()
48 {
49     srand(20020627);
50     n=read(); m=read();
51     for (int i=1; i<=m; ++i)
52     {
53         int u=read(),v=read();
54         add(u,v); add(v,u);
55     }
56     DFS(1,0);
57     q=read();
58     while (q--)
59     {
60         memset(d,0,sizeof(d));
61         k=read(); int flag=1;
62         for (int i=1; i<=k; ++i)
63         {
64             int x=val[read()^ans];
65             for (int i=30; i>=0; --i)
66                 if (x&(1<<i))
67                 {
68                     if (!d[i]) {d[i]=x; break;}
69                     x^=d[i];
70                 }
71             if (!x) flag=0;
72         }
73         ans+=flag;
74         if (flag) puts("Connected");
75         else puts("Disconnected");
76     }
77 }