由题意可知 图是由 环 和 直链组成的 若 环能到达 那么 能到达的直链 都能和环组成 一组数 因为 每个到达环的路径再回来 把到环上的直链抵消了
所以我们 可以考虑 把环上的值全都扔进线性基 再看直链上有哪些值是能和环组成新值的
如果 线性基里能组成的 那么链上的就无需加入 若不能组成的 那么 一定会有一位 是线性基里所没有的那么答案就是 (1<<sz) * s.size() s表示线性基组成不了的数的个数 sz表示线性基里的元素个数
2.删边我们可以考虑离线从后往前加边 若加的边多环 那么重组一下线性基 并且重组一下 s.size() 若没有影响 就先存着 防止后面会用上 复杂度为 60nlogn
#include<iostream>
#include<cstring>
#include<set>
#include<vector>
using namespace std;
const int N = 2e5 + 10,M = N * 8;
typedef long long ll;
int head[N],to[M],last[M];ll w[M],cnt;
void add(int a,int b,ll c){
to[++cnt] = b;
w[cnt] = c;
last[cnt] = head[a];
head[a] = cnt;
}
int flag[N],id[N],fa[N],x[N],y[N];ll z[N];
int get(int x){
if(fa[x] == x) return x;
return fa[x] = get(fa[x]);
}
int n,m,q;
set<ll>s;
vector<int>R[N];
ll dis[N],p[N],ans[N];
ll dt(ll x){
for(int i = 60; i >= 0; i--){
if((x & (1ll << i)) && p[i]) x ^= p[i];
}
return x;
}
void dfs(int x,int lastt){
s.insert(dt(dis[x]));
for(int i = head[x]; i != -1; i = last[i]){
int j = to[i];
if(j == lastt) continue;
dis[j] = dis[x] ^ w[i];
dfs(j,x);
}
}
ll sz;
bool insert(ll x){
for(int i = 60; i >= 0; i--){
if(x & (1ll << i)){
if(p[i]){
x ^= p[i];
}else{
p[i] = x;
sz++;
return true;
}
}
}
return false;
}
void build(){
set<ll>S;
for(auto it = s.begin(); it != s.end(); it++) S.insert(dt(*it));
swap(S,s);
}
int main() {
for(int i = 0; i <= 2e5; i++) fa[i] = i,head[i] = -1;
cin >> n >> m >> q;
for(int i = 1; i <= m; i++){
scanf("%d%d%lld",&x[i],&y[i],&z[i]);
}
for(int i = 1; i <= q; i++){
scanf("%d",&id[i]);
flag[id[i]] = 1;
}
for(int i = 1; i <= m; i++){
if(flag[i]) continue;
if(get(x[i]) != get(y[i])){
add(x[i],y[i],z[i]);
add(y[i],x[i],z[i]);
fa[get(x[i])] = get(y[i]);
}
}
s.insert(0);
dfs(1,0);
for(int i = 1; i <= m; i++){
if(flag[i]) continue;
if(get(x[i]) == get(1)) insert(dis[x[i]] ^ dis[y[i]] ^ z[i]); // 环
else R[get(x[i])].push_back(i);
}
build();
ans[q + 1] = (1ll << sz) * s.size();
for(int i = q; i >= 1; i--){
ll u = x[id[i]],v = y[id[i]],ww = z[id[i]];
if(get(u) == get(v)){
//环
if(get(u) == get(1)){
//和1有关的环
if(insert(dis[u] ^ dis[v] ^ ww)) build();
}else R[get(u)].push_back(id[i]); //后面添边可能 出现与1相关的新环
}else{
if(get(u) == get(1) || get(v) == get(1)){
if(get(v) == get(1)) swap(u,v);
dis[v] = dis[u] ^ ww; //图变了 可能有新环 或者值
add(u,v,ww);
dfs(v,u);
bool st = false;
for(int i : R[get(v)]){
if(insert(dis[x[i]] ^ dis[y[i]] ^ z[i])) st = true;
}
if(st) build();
fa[get(u)] = get(v);
}else{
add(u,v,ww);
add(v,u,ww);
u = get(u),v = get(v);
if(R[u].size() > R[v].size()) swap(u,v);
for(int x : R[u]) R[v].push_back(x);
fa[u] = v;
}
}
ans[i] = (1ll << sz) * s.size();
}
for(int i = 1; i <= q + 1; i++) cout <<ans[i] << endl;
return 0;
}