BZOJ3569: DZY Loves Chinese II
Description
神校XJ之学霸兮,Dzy皇考曰JC。
摄提贞于孟陬兮,惟庚寅Dzy以降。
纷Dzy既有此内美兮,又重之以修能。
遂降临于OI界,欲以神力而凌♂辱众生。
今Dzy有一魞歄图,其上有N座祭坛,又有M条膴蠁边。
时而Dzy狂WA而怒发冲冠,神力外溢,遂有K条膴蠁边灰飞烟灭。
而后俟其日A50题则又令其复原。(可视为立即复原)
然若有祭坛无法相互到达,Dzy之神力便会大减,于是欲知其是否连通。
Input
第一行N,M
接下来M行x,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
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
Connected
Connected
Connected
Disconnected
HINT
N≤100000 M≤500000 Q≤50000 1≤K≤15
数据保证没有重边与自环
Tip:请学会使用搜索引擎
很厉害的思路,先随便找出一棵生成树,然后对非树边随便赋权值,对于树边权值赋为所有覆盖它的非树边的权值异或和。
那么询问时高斯消元一下判断是否有异或为0的子集,如果有就认为整张图不再连通。
竟然被卡了两次随机种子。。。
#include<cstdio> #include<cctype> #include<queue> #include<cstring> #include<algorithm> #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define ren for(int i=first[x];i;i=edges[i].next) using namespace std; const int BufferSize=1<<16; char buffer[BufferSize],*head,*tail; inline char Getchar() { if(head==tail) { int l=fread(buffer,1,BufferSize,stdin); tail=(head=buffer)+l; } return *head++; } inline int read() { int x=0,f=1;char c=Getchar(); for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1; for(;isdigit(c);c=Getchar()) x=x*10+c-'0'; return x*f; } const int maxn=100010; const int maxm=200010; struct Edge {int to,next;}edges[maxm<<1]; int n,m,e=1,clo,f[maxn],vis[maxn],A[maxm],first[maxn]; void AddEdge(int u,int v) { edges[++e]=(Edge){v,first[u]};first[u]=e; edges[++e]=(Edge){u,first[v]};first[v]=e; } void dfs(int x,int fa) { vis[x]=++clo; ren { Edge& e=edges[i]; if(fa==e.to) continue; if(!vis[e.to]) { dfs(e.to,x); A[i>>1]=f[e.to]; f[x]^=f[e.to]; } else if(vis[x]>vis[e.to]) { A[i>>1]=rand()+1; f[x]^=A[i>>1]; f[e.to]^=A[i>>1]; } } } int S[25],N; int gauss() { int i,k=0; dwn(j,30,0) { for(i=k+1;i<=N;i++) if(S[i]>>j&1) break; if(i==N+1) continue; swap(S[++k],S[i]); for(i=1;i<=N;i++) if(i!=k&&(S[i]>>j&1)) S[i]^=S[k]; } return S[N]>0; } int main() { srand(52501); n=read();m=read(); rep(i,1,m) AddEdge(read(),read()); dfs(1,-1); dwn(T,read(),1) { N=read(); rep(i,1,N) S[i]=A[read()]; int ans=gauss(); puts(ans?"Connected":"Disconnected"); } return 0; }