[高斯消元 线性基 树 记数] BZOJ 2322 [BeiJing2011]梦想封印
2016-07-06 22:57
274 查看
删边变加边
如果加的是非树边 相当于加了一个环 加入线性基中
如果加入的是树边 就dfs扩展树
两条链是等价的 相当于 他们用线性基消过后是一样的 用set维护
解是不等价链的个数*1<<线性基的个数-1
减一是要去掉0
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<set>
using namespace std;
typedef long long ll;
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;
}
inline void read(ll &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=5005;
const int M=20005;
const int K=63;
struct edge{
int u,v,next; ll w;
}G[M<<1]; int can[M<<1];
int head
,inum=1;
inline void add(int u,int v,ll w,int p){
G[p].u=u; G[p].v=v; G[p].w=w; G[p].next=head[u]; head[u]=p;
}
int n,m;
ll depth
; int vst
;
ll a[M<<1]; int tot,base[K+5];
inline ll Ext(ll x){
for (int p=K;~p;p--)
if (x>>p&1)
if (base[p])
x^=a[base[p]];
return x;
}
inline void Ins(ll x){
for (int p=K;~p;p--)
if (x>>p&1)
if (base[p])
x^=a[base[p]];
else{
a[base[p]=++tot]=x; return;
}
}
ll chain
; int cnt;
inline ll calc()
{
set<ll> Set;
int pnt=0;
for (int i=1;i<=cnt;i++)
{
ll x=Ext(chain[i]);
if (Set.find(x)==Set.end())
chain[++pnt]=chain[i],Set.insert(x);
}
cnt=pnt;
return (ll)cnt*(1LL<<tot)-1;
}
#define V G[p].v
inline void dfs(int u,int fa){
vst[u]=1; chain[++cnt]=depth[u];
for (int p=head[u];p;p=G[p].next)
if (V!=fa && !can[p])
{
if (!vst[V])
depth[V]=depth[u]^G[p].w,dfs(V,u);
else
Ins(depth[V]^depth[u]^G[p].w);
}
}
int Q,ed[M];
ll ans[M];
int main()
{
int iu,iv; ll iw;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); read(m); read(Q);
for (int i=1;i<=m;i++)
read(iu),read(iv),read(iw),add(iu,iv,iw,++inum),add(iv,iu,iw,++inum);
for (int i=1;i<=Q;i++) read(ed[i]),can[ed[i]<<1]=can[ed[i]<<1|1]=1;
// for (int i=Q;i>=Q-10;i--) printf("%d %d %d\n",G[ed[i]<<1].u,G[ed[i]<<1].v,G[ed[i]<<1].w);
dfs(1,0);
ans[Q+1]=calc();
for (int i=Q;i;i--)
{
iu=G[ed[i]<<1].u; iv=G[ed[i]<<1].v;
if (vst[iu] && vst[iv]) Ins(depth[iv]^depth[iu]^G[ed[i]<<1].w);
if (vst[iu] && !vst[iv]) depth[iv]=depth[iu]^G[ed[i]<<1].w,dfs(iv,iu);
if (!vst[iu] && vst[iv]) depth[iu]=depth[iv]^G[ed[i]<<1].w,dfs(iu,iv);
can[ed[i]<<1]=can[ed[i]<<1|1]=0;
ans[i]=calc();
}
for (int i=1;i<=Q+1;i++)
printf("%lld\n",ans[i]);
return 0;
}
如果加的是非树边 相当于加了一个环 加入线性基中
如果加入的是树边 就dfs扩展树
两条链是等价的 相当于 他们用线性基消过后是一样的 用set维护
解是不等价链的个数*1<<线性基的个数-1
减一是要去掉0
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<set>
using namespace std;
typedef long long ll;
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;
}
inline void read(ll &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=5005;
const int M=20005;
const int K=63;
struct edge{
int u,v,next; ll w;
}G[M<<1]; int can[M<<1];
int head
,inum=1;
inline void add(int u,int v,ll w,int p){
G[p].u=u; G[p].v=v; G[p].w=w; G[p].next=head[u]; head[u]=p;
}
int n,m;
ll depth
; int vst
;
ll a[M<<1]; int tot,base[K+5];
inline ll Ext(ll x){
for (int p=K;~p;p--)
if (x>>p&1)
if (base[p])
x^=a[base[p]];
return x;
}
inline void Ins(ll x){
for (int p=K;~p;p--)
if (x>>p&1)
if (base[p])
x^=a[base[p]];
else{
a[base[p]=++tot]=x; return;
}
}
ll chain
; int cnt;
inline ll calc()
{
set<ll> Set;
int pnt=0;
for (int i=1;i<=cnt;i++)
{
ll x=Ext(chain[i]);
if (Set.find(x)==Set.end())
chain[++pnt]=chain[i],Set.insert(x);
}
cnt=pnt;
return (ll)cnt*(1LL<<tot)-1;
}
#define V G[p].v
inline void dfs(int u,int fa){
vst[u]=1; chain[++cnt]=depth[u];
for (int p=head[u];p;p=G[p].next)
if (V!=fa && !can[p])
{
if (!vst[V])
depth[V]=depth[u]^G[p].w,dfs(V,u);
else
Ins(depth[V]^depth[u]^G[p].w);
}
}
int Q,ed[M];
ll ans[M];
int main()
{
int iu,iv; ll iw;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); read(m); read(Q);
for (int i=1;i<=m;i++)
read(iu),read(iv),read(iw),add(iu,iv,iw,++inum),add(iv,iu,iw,++inum);
for (int i=1;i<=Q;i++) read(ed[i]),can[ed[i]<<1]=can[ed[i]<<1|1]=1;
// for (int i=Q;i>=Q-10;i--) printf("%d %d %d\n",G[ed[i]<<1].u,G[ed[i]<<1].v,G[ed[i]<<1].w);
dfs(1,0);
ans[Q+1]=calc();
for (int i=Q;i;i--)
{
iu=G[ed[i]<<1].u; iv=G[ed[i]<<1].v;
if (vst[iu] && vst[iv]) Ins(depth[iv]^depth[iu]^G[ed[i]<<1].w);
if (vst[iu] && !vst[iv]) depth[iv]=depth[iu]^G[ed[i]<<1].w,dfs(iv,iu);
if (!vst[iu] && vst[iv]) depth[iu]=depth[iv]^G[ed[i]<<1].w,dfs(iu,iv);
can[ed[i]<<1]=can[ed[i]<<1|1]=0;
ans[i]=calc();
}
for (int i=1;i<=Q+1;i++)
printf("%lld\n",ans[i]);
return 0;
}
相关文章推荐
- 利用iframe来实现ajax文件上传
- 使用 Swift 在 iOS 10 中集成 Siri —— SiriKit 教程
- leetcode-Set Matrix Zeroes
- Redis 安装
- 剖析LRU算法及LinkedHashMap源码实现机制
- Java之WeakReference与SoftReference使用讲解
- ActivityLifecycle 生命周期
- 前景检测算法(五)--GMM,GMM2,GMG
- java冒泡排序和选择排序法
- Android &Swift iOS开发:语言与框架对比
- Redis 简介
- 总结
- WAS的SystemOut.log中报错“ADMS0015E”
- Windows下利用py2exe生成静默运行的命令行程序
- 通过 脚本执行 kettle 的作业 命令
- codevs 4919 线段树练习4
- 4并查集的合并与删除
- Android之Handler与多线程
- 1013 Problem M
- matlab中关于pushbotton的左键双击响应问题