您的位置:首页 > 其它

[高斯消元 线性基 树 记数] 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: