您的位置:首页 > 其它

BZOJ 3569 DZY Loves Chinese(BZOJ 3563) II 线性基

2017-06-21 10:52 441 查看
题目大意:给出一张n个点m条边的无向图。进行q次询问,问删掉某k条边后图是否联通。强制在线

N≤100000 M≤500000 Q≤50000 1≤K≤15

这题好神啊…

首先找出图中的一棵生成树,对于每一条非树边赋上一个随机值,每条树边等于覆盖它的非树边的权值的异或和,那么这个图不连通当存在一个删掉的边的子集的异或和为0。

线性基搞一下看能不能异或出0。

#include <cstdio>
#include <algorithm>
#include <cstring>
#define N 100005
using namespace std;
int RAND() { return (rand()<<16)+rand(); }
struct Edge {
int to,nxt;
Edge() {}
Edge(int _to,int _nxt):to(_to),nxt(_nxt) {}
}e[N*10];
int n,m,T,tot=1,top,ans,s[20],fir
,val[N*5],p
;
bool vis
;
void Add_Edge(int u,int v) {
e[++tot]=Edge(v,fir[u]), fir[u]=tot;
e[++tot]=Edge(u,fir[v]), fir[v]=tot;
return ;
}
void dfs1(int x,int from) {
vis[x]=true;
for(int i=fir[x];~i;i=e[i].nxt) {
if(e[i].to==from) continue;
if(!vis[e[i].to]) dfs1(e[i].to,x);
else if(!val[i/2]) {
int rd=RAND();
val[i/2]=rd;
p[x]^=rd;
p[e[i].to]^=rd;
}
}
return ;
}
void dfs2(int x,int from) {
vis[x]=true;
for(int i=fir[x];~i;i=e[i].nxt) {
if(vis[e[i].to]) continue;
dfs2(e[i].to,x);
val[i/2]=p[e[i].to];
p[x]^=p[e[i].to];
}
return ;
}
void Gauss() {
int j=0;
for(int k=30;~k;--k) {
int i;
for(i=j+1;i<=top;++i)
if(s[i]&(1<<k))
break;
if(i==top+1) continue;
swap(s[i],s[++j]);
for(int i=1;i<=top;++i)
if(s[i]&(1<<k) && i!=j)
s[i]^=s[j];
}
return ;
}
int main() {
memset(fir,-1,sizeof fir);
scanf("%d%d",&n,&m);
for(int i=1,x,y;i<=m;++i) scanf("%d%d",&x,&y), Add_Edge(x,y);
dfs1(1,0);
memset(vis,false,sizeof vis);
dfs2(1,0);
for(scanf("%d",&T);T;--T) {
scanf("%d",&top);
for(int i=1;i<=top;++i) scanf("%d",s+i), s[i]=val[s[i]^ans];
Gauss();
if(s[top]) ++ans;
puts(s[top] ? "Connected" : "Disconnected");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: