Description
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190215223747942.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNjQ5NDE2,size_16,color_FFFFFF,t_70)
Data Constraint
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190215223815338.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNjQ5NDE2,size_16,color_FFFFFF,t_70)
Solution
- 看到异或的种数我呢吧不难想到线性基。
- 是否能将每一个环独立出来使得它们能够任意组合呢?这样才能满足线性基的性质。
- 我们先建一棵DFS树,剩下一些返祖边。
- 每一条返祖边对应一个环。
- 这些环都是互不影响的。
- 我们在任意一个点都可以得到正好这个环的贡献并回到原点(只要它们联通)。
- 于是我们的任意路径就变成了从1出发的一条树链,加上任意的环。
- 我们需要统计这样有多少种。
- 将环加入线性基中,如果一条路径的权值的某个位置为1,并且线性基这个位置不为空,就异或一下,最后得到的路径权值就变成了最小表示。也就是说这个时候相同的路径是等价的。
- 答案就是:不同的路径条数*2^线性基大小。
- 考虑删边,不妨离线变为加边。
- 如果加了一条树边,就往下遍历新的子树,因为这些点都是没有遍历过的,所以时间复杂度有保证。
- 对于每一个新的环,如果更新了线性基就重新计算所有答案,因为线性基只会被更新log次。
- 最后计算答案。
- 时间复杂度O(nlogw+nlog2w)
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define maxn 100005
#define maxm 400005
#define ll long long
using namespace std;
int n,m,q,i,j,k,tim;
int em,e[maxm],nx[maxm],ls[maxm],bz[maxm],que[maxm];
ll x,y,z,a[maxm][3],ec[maxm],ans[maxm],sum[maxn],p[63],Ans,v[maxn],siz;
int vis[maxm],d[maxm],tot,dep[maxm];
void insert(int x,int y,ll z){
em++;
e[em]=y;
nx[em]=ls[x];
ls[x]=em;
ec[em]=z;
em++; e[em]=x; nx[em]=ls[y]; ls[y]=em; ec[em]=z;
}
int add(ll x){
for(ll i=62;i>=0;i--) if (x>>i){
if (!(x>>i)) continue;
if (!p[i]) {p[i]=x;siz++;return 1;}
x^=p[i];
}
return 0;
}
ll view(ll x){
for(ll i=62;i>=0;i--) if (((x>>i)&1)&&p[i])
x^=p[i];
return x;
}
int dfs(int x,int p){
vis[x]=1; d[++tot]=x; dep[x]=dep[p]+1;
int tmp=0;
for(int i=ls[x];i;i=nx[i]) if (e[i]!=p){
if (!vis[e[i]]) sum[e[i]]=sum[x]^ec[i],tmp|=dfs(e[i],x);
else {
if (dep[e[i]]<dep[x]) tmp|=add(ec[i]^sum[x]^sum[e[i]]);
}
}
return tmp;
}
const ll mo=3000007,c1=17,c2=233;
int hs[mo];
void push_hash(ll x){hs[(x%mo*c1+c2)%mo]=0;}
void add_hash(ll x){
ll tmp=(x%mo*c1+c2)%mo;
if (!hs[tmp]) Ans++;
hs[tmp]=1;
}
void redo(){
for(i=1;i<=n;i++) if (vis[i]) push_hash(v[i]);
Ans=0;
for(i=1;i<=n;i++) if (vis[i]) add_hash(v[d[i]]=view(sum[d[i]]));
}
int main(){
freopen("travel.in","r",stdin);
freopen("travel.out","w",stdout);
scanf("%d%d%d",&n,&m,&q);
for(i=1;i<=m;i++) scanf("%lld%lld%lld",&a[i][0],&a[i][1],&a[i][2]);
for(i=1;i<=q;i++) scanf("%d",&que[i]),bz[que[i]]=1;
tim=q+1;
for(i=1;i<=m;i++) if (!bz[i]) insert(a[i][0],a[i][1],a[i][2]);
sum[1]=0;
tot=0; dfs(1,0);
Ans=0; for(i=1;i<=tot;i++) add_hash(v[d[i]]=view(sum[d[i]]));
ans[q+1]=Ans*(1ll<<siz);
for(tim=q;tim;tim--){
x=a[que[tim]][0],y=a[que[tim]][1],z=a[que[tim]][2];
insert(x,y,z);
if (vis[x]&&vis[y]) {
if (add(z^sum[x]^sum[y])) redo();
} else
if (vis[x]||vis[y]){
if (vis[y]) swap(x,y);
tot=0; int tmp=0;
sum[y]=sum[x]^z,tmp=dfs(y,x);
if (tmp) redo(); else
for(i=1;i<=tot;i++) add_hash(v[d[i]]=view(sum[d[i]]));
}
ans[tim]=Ans*(1ll<<siz);
}
for(i=1;i<=q+1;i++) printf("%lld\n",ans[i]);
}