[高斯消元 线性基 生成树 随机化权值Xor] BZOJ 3569 DZY Loves Chinese II
2016-06-06 06:54
351 查看
很好的建图姿势:
我们找到这个图的任意一棵生成树 然后对于每条非树边将其的权值赋为一个随机数
对于每条树边 我们将这条树边的权值设为所有覆盖这条树边的边权的异或和
那么图不连通当且仅当删除一条树边和覆盖这条树边的所有边集 而由于刚才的处理一条树边和覆盖这条边的所有边集的异或和为零
于是问题转化成了对于给定的k条边是否存在一个边权的异或和为零的子集 果断高斯消元 由于使用了随机化所以碰撞率极低
还不是很熟悉高斯消元那一套理论啊
我们找到这个图的任意一棵生成树 然后对于每条非树边将其的权值赋为一个随机数
对于每条树边 我们将这条树边的权值设为所有覆盖这条树边的边权的异或和
那么图不连通当且仅当删除一条树边和覆盖这条树边的所有边集 而由于刚才的处理一条树边和覆盖这条边的所有边集的异或和为零
于是问题转化成了对于给定的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; }
相关文章推荐
- [组合数学] BZOJ 2467 [中山市选2010]生成树
- [DP Euler Zigzag Number] BZOJ 1925 [Sdoi2010]地精部落
- 计算节点宕机了怎么办?- 每天5分钟玩转 OpenStack(43)
- 计算节点宕机了怎么办?- 每天5分钟玩转 OpenStack(43)
- 计算节点宕机了怎么办?- 每天5分钟玩转 OpenStack(43)
- Strobogrammatic Number
- [最大密度子图 最小割] BZOJ 1312 Neerc2006 Hard Life
- MySQL读取不重复的数据
- 大型网站架构系列:缓存在分布式系统中的应用(一)
- Closest Binary Search Tree Value
- 成为C++高手之头文件与条件编译
- 语音增强原理之噪声估计
- 结束SpringMVC
- SpringMVC小结(四)
- SpringMVC之安全性(三)Twitter登入
- SpringMVC之安全性(二)登录界面
- SpringMVC之安全性(一)
- C#之四十四 滑铁卢战役
- C#之四十四 滑铁卢战役
- C#之四十四 滑铁卢战役