神校XJ之学霸兮,Dzy皇考曰JC。node
摄提贞于孟陬兮,唯庚寅Dzy以降。ios
纷Dzy既有此内美兮,又重之以修能。git
遂降临于OI界,欲以神力而凌♂辱众生。搜索引擎
今Dzy有一魞歄图,其上有N座祭坛,又有M条膴蠁边。spa
时而Dzy狂WA而怒发冲冠,神力外溢,遂有K条膴蠁边灰飞烟灭。code
然后俟其日A50题则又令其复原。(可视为当即复原)索引
然如有祭坛没法相互到达,Dzy之神力便会大减,因而欲知其是否连通。ip
第一行N,Mget
接下来M行x,y:表示M条膴蠁边,依次编号input
接下来一行Q
接下来Q行:
每行第一个数K然后K个编号c1~cK:表示K条边,编号为c1~cK
为了体如今线,c1~cK均需异或以前回答为连通的个数
对于每组询问,输出到输出文件zap.out一个正整数,表示知足条件的整数对数。
对于每一个询问输出:连通则为‘Connected’,不连通则为‘Disconnected’
(不加引号)
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
Connected
Connected
Connected
Connected
Disconnected
N≤100000 M≤500000 Q≤50000 1≤K≤15
数据保证没有重边与自环
Tip:请学会使用搜索引擎
n个点,m条无向边,求断掉k条边后,残图是否仍然联通,强制在线。
考虑先构造出原图的一棵生成树,对于每条非树边rand一个权值。
每条树边的权值设为能够与当前边构成回路的边的权值异或和。
那么,若是当前图不连通,当且仅当一条树边被删除且覆盖了这条树边的全部边都被删除了。
此时,这些边的权值异或起来为0。
问题转化为:
给定边中是否存在若干个权值异或起来为0。
此时即可使用线性基求解。
简单的建树操做,任意一棵生成树都可。
注意用\(fa[ ]\)记录父亲,并用\(use[ ]\)记录好哪些是树上的边,方便以后处理。
void Dfs1(int x){ vis[x]=1; for(int i=h[x];i;i=g[i].next){ int to=g[i].to; if(vis[to])continue; use[i>>1]=1,fa[to]=x; Dfs1(to); } }
由于此时是一棵树,因此增长一条边会且仅会产生一条回路。
那么,咱们给一条非树边的两点附上权值,
在上传的过程当中把该权值附给与父亲节点相连的边,这样就能够覆盖至整条回路了。
void Dfs2(int x){ for(int i=h[x];i;i=g[i].next){ int to=g[i].to; if(fa[to]^x)continue; Dfs2(to); e[i>>1].val^=val[to]; val[x]^=val[to]; } } for(int i=1;i<=m;i++){ if(use[i])continue; int x=(LL)rand*rand()%1000000000+1; e[i].val=x; val[e[i].x]^=x,val[e[i].y]^=x; }
#include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<cstdio> #include<iomanip> #include<cstdlib> #include<ctime> #define MAXN 0x7fffffff typedef long long LL; const int N=100005,M=500005; using namespace std; inline int Getint(){register int x=0,f=1;register char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}return x*f;} int h[N],cnt=1; struct node{int to,next;}g[M<<1]; void AddEdge(int x,int y){g[++cnt].to=y,g[cnt].next=h[x],h[x]=cnt;} struct Edge{int x,y,val;}e[M]; int fa[N],val[M]; bool vis[N],use[M]; void Dfs1(int x){ vis[x]=1; for(int i=h[x];i;i=g[i].next){ int to=g[i].to; if(vis[to])continue; use[i>>1]=1,fa[to]=x; Dfs1(to); } } void Dfs2(int x){ for(int i=h[x];i;i=g[i].next){ int to=g[i].to; if(fa[to]^x)continue; Dfs2(to); e[i>>1].val^=val[to]; val[x]^=val[to]; } } int p[35]; bool Insert(int x){ for(int i=31;i>=0;i--){ if(!((x>>i)&1))continue; if(!p[i]){p[i]=x;break;} x^=p[i]; } return x>0; } int main(){ srand(time(0)); int n=Getint(),m=Getint(); for(int i=1;i<=m;i++){ int x=e[i].x=Getint(),y=e[i].y=Getint(); AddEdge(x,y),AddEdge(y,x); } Dfs1(1); for(int i=1;i<=m;i++){ if(use[i])continue; int x=(LL)rand()*rand()%1000000000+1; e[i].val=x; val[e[i].x]^=x,val[e[i].y]^=x; } Dfs2(1); int Q=Getint(),ans=0; while(Q--){ int k=Getint(); memset(p,0,sizeof(p)); bool ok=0; for(int i=1;i<=k;i++){ int x=Getint()^ans; if(!Insert(e[x].val))ok=1; } if(!ok)puts("Connected"),ans++; else puts("Disconnected"); } return 0; }