Description
神校 XJ 之学霸兮, Dzy 皇考曰 JC 。
摄提贞于孟陬兮,惟庚寅 Dzy 以降。
纷 Dzy 既有此内美兮,又重之以修能。
遂降临于 OI 界,欲以神力而凌♂辱众生。
今
Dzy
有一魞歄图,其上有
N
座祭坛,又有
时而 Dzy 狂 WA 而怒发冲冠,神力外溢,遂有 K 条膴蠁边灰飞烟灭。
而后俟其日
然若有祭坛无法相互到达, Dzy 之神力便会大减,于是欲知其是否连通。
Input
第一行 N,M
接下来
M
行
接下来一行
接下来 Q 行:
每行第一个数
为了体现在线, c1 ~ cK 均需异或之前回答为连通的个数
(N≤1e5,M≤5e5,Q≤5e4,1≤K≤15)
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
Solution
先找到原图的一个生成树,给非树边随机边权,定义点权为以其为端点的非树边边权异或和,给树定向之后,树边的权值为其深度较深的端点点权,这样如果删去的边集中存在一个子集使得其权值异或和为 0 <script type="math/tex" id="MathJax-Element-88">0</script>,则说明一条树边及其周围的非树边全部被删掉,由于边权是随机的所以出错率很小
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<ctime>
using namespace std;
namespace fastIO
{
#define BUF_SIZE 100000
//fread -> read
bool IOerror=0;
inline char nc()
{
static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
if(p1==pend)
{
p1=buf;
pend=buf+fread(buf,1,BUF_SIZE,stdin);
if(pend==p1)
{
IOerror=1;
return -1;
}
}
return *p1++;
}
inline bool blank(char ch)
{
return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';
}
inline void read(int &x)
{
char ch;
while(blank(ch=nc()));
if(IOerror)return;
for(x=ch-'0';(ch=nc())>='0'&&ch<='9';x=x*10+ch-'0');
}
#undef BUF_SIZE
};
using namespace fastIO;
const int maxn=100005,maxm=500005;
struct node
{
int v,next;
}edge[maxm*2];
int n,m,q,res,vis[maxn],val[maxn],weight[maxm],tot,head[maxn],base[33];
void add(int u,int v)
{
edge[++tot].v=v,edge[tot].next=head[u],head[u]=tot;
}
void dfs(int u,int fa)
{
vis[u]=res++;
for(int i=head[u];i;i=edge[i].next)
{
int v=edge[i].v;
if(v==fa)continue;
if(!vis[v])
{
dfs(v,u);
weight[i/2]=val[v];
val[u]^=val[v];
}
else if(vis[u]>vis[v])
{
weight[i/2]=rand()+1;
val[u]^=weight[i/2];
val[v]^=weight[i/2];
}
}
}
int main()
{
srand(19971109);
read(n);read(m);//scanf("%d%d",&n,&m);
tot=res=1;
while(m--)
{
int u,v;
read(u);read(v);//scanf("%d%d",&u,&v);
add(u,v),add(v,u);
}
dfs(1,0);
int num=0;
read(q);//scanf("%d",&q);
while(q--)
{
int k,temp,flag=0;
read(k);//scanf("%d",&k);
memset(base,0,sizeof(base));
while(k--)
{
read(temp);//scanf("%d",&temp);
temp=weight[temp^num];
for(int i=30;i>=0;i--)
if(temp>>i&1)
{
if(!base[i])
{
base[i]=temp;
break;
}
else temp^=base[i];
}
if(!temp)flag=1;
}
if(flag)printf("Disconnected\n");
else printf("Connected\n"),num++;
}
return 0;
}