您的位置:首页 > 其它

[高斯消元 线性基 生成树 随机化权值Xor] BZOJ 3569 DZY Loves Chinese II

2016-06-06 06:54 351 查看
很好的建图姿势:

我们找到这个图的任意一棵生成树 然后对于每条非树边将其的权值赋为一个随机数

对于每条树边 我们将这条树边的权值设为所有覆盖这条树边的边权的异或和

那么图不连通当且仅当删除一条树边和覆盖这条树边的所有边集 而由于刚才的处理一条树边和覆盖这条边的所有边集的异或和为零

于是问题转化成了对于给定的k条边是否存在一个边权的异或和为零的子集 果断高斯消元 由于使用了随机化所以碰撞率极低

还不是很熟悉高斯消元那一套理论啊

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;

inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}

inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

const int N=100005,M=500005;

struct edge{
int u,v; int next;
};

edge G[M<<1];
int head
,inum=1;

inline void add(int u,int v,int p){
G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;
}

int n,m;
int a[M],b[M];
int vst
;

#define V G[p].v
inline void dfs1(int u,int fa){
vst[u]=1;
for (int p=head[u];p;p=G[p].next)
if (V!=fa)
{
if (!vst[V])
dfs1(V,u);
else if (!~a[p>>1])
{
a[p>>1]=rand();
b[V]^=a[p>>1]; b[u]^=a[p>>1];
}
}
}

inline void dfs2(int u,int fa){
vst[u]=1;
for (int p=head[u];p;p=G[p].next)
if (V!=fa && !vst[V])
{
dfs2(V,u);
a[p>>1]=b[V];
b[u]^=b[V];
}
}

int K,s[M];

inline void Gauss()
{
int k=0,i;
for (int j=1<<30;j;j>>=1)
{
for (i=k+1;i<=K;i++)
if (s[i]&j)
break;
if (i==K+1) continue;
swap(s[i],s[++k]);
for (int i=k+1;i<=K;i++)
if (s[i]&j)
s[i]^=s[k];
}
}

int main()
{
int x,y,Q,lastans=0;
srand(10086);
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); read(m);
for (int i=1;i<=m;i++)
read(x),read(y),add(x,y,++inum),add(y,x,++inum);
memset(a,-1,sizeof(a));
dfs1(1,0);
cl(vst);
dfs2(1,0);
read(Q);
while (Q--)
{
read(K);
for (int i=1;i<=K;i++)
read(x),s[i]=a[x^lastans];
Gauss();
lastans+=(bool)s[K];
if (s[K])
printf("Connected\n");
else
printf("Disconnected\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: