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

Sample Output

Connected
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;
}

  

posted @ 2016-04-12 21:02  wzj_is_a_juruo  阅读(326)  评论(0编辑  收藏  举报