题目大意: 给一张无向图,每次询问删掉一些边,然后问图是否连通,强制在线。
题解1
DZY Loves Chinese 和 DZY Loves Chinese II 的区别就是强制在线时 k k k 是否需要异或。
DZY Loves Chinese 是需要的,而这就成了一个大性质:你可以通过读入数据得到真正的 k k k,异或上他给的 k k k 就能求出前面有多少个Connected
,所以你可以借此得到前 q − 1 q-1 q−1 个询问的答案……最后一问暴力做即可。
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 500010
int n,m,q;
struct edge{
int x,y;}e[maxn];
int d[maxn],tot,ans[maxn];
bool isendl(char x){
return x=='\r'||x=='\n';}
int fa[maxn];
int findfa(int x){
return x==fa[x]?x:fa[x]=findfa(fa[x]);}
void link(int x,int y){
x=findfa(x);y=findfa(y);
if(x!=y)fa[y]=x;
}
bool v[maxn];
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++)scanf("%d %d",&e[i].x,&e[i].y);
scanf("%d",&q);
for(int i=1,k;i<=q;i++){
scanf("%d",&k);tot=0;
while(!isendl(getchar()))scanf("%d",&d[++tot]);
ans[i]=tot^k;
}
for(int i=1;i<q;i++)puts(ans[i+1]-ans[i]?"Connected":"Disconnected");
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=tot;i++)v[d[i]^ans[q]]=true;
for(int i=1;i<=m;i++)if(!v[i])link(e[i].x,e[i].y);
for(int i=1;i<=n;i++)if(findfa(i)!=findfa(1))return printf("Disconnected"),0;
printf("Connected");
}
题解2
这题就没有那么蛋疼的性质了。
考虑求出一棵dfs树,那么剩下的非树边一定是返祖边。考虑随机给每条非树边一个权值,然后令一条树边的权值为所有覆盖它的非树边的权值异或和。
那么,删掉一些边能使图不连通,有两种情况:
- 删掉了一个树边和所有覆盖它的非树边
- 对于两条树边 E 1 , E 2 E_1,E_2 E1,E2,删掉了一些覆盖他们的非树边,然后对于剩下的非树边,覆盖 E 1 E_1 E1 的非树边集合与覆盖 E 2 E_2 E2 的非树边集合相同,然后删除掉 E 1 , E 2 E_1,E_2 E1,E2。
注意到在这两种情况中,被删掉的边的异或和都是 0 0 0。
所以你只需要判断每次询问删掉的边中,是否存在若干条边的异或和为 0 0 0 即可,这个可以用线性基简单判断。
代码如下:
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
#define maxn 500010
#define ll long long
int n,m,q;
struct edge{
int y,z,next;}e[maxn<<1];
int first[maxn],len=0;
void buildroad(int x,int y,int z){
e[++len]=(edge){
y,z,first[x]};first[x]=len;}
vector<int> E[maxn];
bool vis[maxn];
int rd(){
static int x0=9904;
x0=(1000000007ll*x0+9904527)%998244353;
return x0;
}
ll val[maxn];
vector<ll> s[maxn];
int dep[maxn],edgeFa[maxn];
void dfs(int x,int fa){
vis[x]=true;
for(int i=first[x];i;i=e[i].next){
int y=e[i].y;if(y==fa)continue;
if(vis[y]){
if(dep[y]>dep[x])continue;
val[e[i].z]=1ll*rd()*rd();
s[x].push_back(val[e[i].z]);
s[y].push_back(val[e[i].z]);
}else{
E[x].push_back(y);
edgeFa[y]=e[i].z;
dep[y]=dep[x]+1;
dfs(y,x);
}
}
}
void dfs2(int x){
for(int y:E[x])dfs2(y),val[edgeFa[x]]^=val[edgeFa[y]];
for(ll i:s[x])val[edgeFa[x]]^=i;
}
struct XXJ{
int d[70];
void clear(){
memset(d,0,sizeof(d));
}
bool insert(int x){
for(int i=62;i>=0;i--){
if(x>>i&1){
if(d[i])x^=d[i];
else return d[i]=x,true;
}
}
return false;
}
}S;
int main()
{
scanf("%d %d",&n,&m);
for(int i=1,x,y;i<=m;i++){
scanf("%d %d",&x,&y);
buildroad(x,y,i);buildroad(y,x,i);
}
dfs(1,0);dfs2(1);
scanf("%d",&q);int ans=0;
for(int i=1,k,x;i<=q;i++){
scanf("%d",&k);bool p=false;S.clear();
while(k--)scanf("%d",&x),x^=ans,p|=(!S.insert(val[x]));
puts(p?"Disconnected":"Connected");
ans+=!p;
}
}