cf题面
洛谷题面
题解:
将全部1连出的边(咱们称之为“关键边”)删掉,获得若干个连通块。
因为1号节点不会包含在 \(\geq\) 4的环里,
若是咱们单独考虑一个连通块,那么它只多是下面两种状况之一(这里套用了cf官方题解的图):
如今考虑题目的限制条件:
一个连通块知足条件的充要条件是:连通块里的全部环对应的边权异或和都能插入一个线性基里。
证实?众所周知,线性基里的数亦或起来不能为0。(不知道的请百度)
而后再回过头来看上述的两种连通块:
第一种:只有1条关键边,那么只有两种贡献:
1.空的线性基(删掉);2.下面连通块获得的线性基(不删)。
第二种:2条关键边,因此有3种状况:
1.空的线性基(删掉);2.下面连通块获得的线性基(删一条边);
3.下面连通块+包含红边的那个环获得的线性基。
接下来考虑合并这些贡献。
因为\(w\)在二进制下只有5位,本质不一样的5位的线性基个数只有374个,
因此咱们能够把这些合法的线性基都预处理出来,并将每一个线性基表示为一个状态。
设 \(f_{i,j}\) 表示前\(i\)个连通块,合并后获得线性基\(j\)的方案数。
转移时一个一个把贡献合并上去就好。(合并就是线性基的合并)
注意到不一样的线性基可能本质相同,咱们须要让线性基惟一,这个能够参考一下个人insert函数:c++
IN insert(int *a,int x){ FOR(i,4,0){ if(!x)return 0; if(!((x>>i)&1))continue; if(!a[i]){ a[i]=x; FOR(j,i-1,0)if((a[i]>>j)&1)a[i]^=a[j]; F(j,i+1,4)if((a[j]>>i)&1)a[j]^=a[i]; return 1; } x^=a[i]; } return 0; }
大概就是若是这一位是1而且有这一位的线性基,就把这个1消掉。
DP数组能够滚动优化。
时间复杂度:O(374* \(log_w\) +(n+m) \(log_w\) +374*n)
代码:git
#include<bits/stdc++.h> using namespace std; #define re register int #define F(x,y,z) for(re x=y;x<=z;x++) #define FOR(x,y,z) for(re x=y;x>=z;x--) typedef long long ll; #define I inline void #define IN inline int #define C(x,y) memset(x,y,sizeof(x)) #define STS system("pause") template<class D>I read(D &res){ res=0;register D g=1;register char ch=getchar(); while(!isdigit(ch)){ if(ch=='-')g=-1; ch=getchar(); } while(isdigit(ch)){ res=(res<<3)+(res<<1)+(ch^48); ch=getchar(); } res*=g; } const int Mod=1e9+7; IN insert(int *a,int x){ FOR(i,4,0){ if(!x)return 0; if(!((x>>i)&1))continue; if(!a[i]){ a[i]=x; FOR(j,i-1,0)if((a[i]>>j)&1)a[i]^=a[j]; F(j,i+1,4)if((a[j]>>i)&1)a[j]^=a[i]; return 1; } x^=a[i]; } return 0; } struct B{ int b[6]; friend bool operator < (B x,B y){ F(i,0,4)if(x.b[i]!=y.b[i])return x.b[i]<y.b[i]; return 0; } friend bool operator == (B x,B y){ F(i,0,4)if(x.b[i]!=y.b[i])return 0; return 1; } }bas[440],now; map<B,int>mp; struct E{ int to,nt,w; }e[202000]; #define T e[k].to int n,m,sn,ans,cnt,X,Y,W,tot,sum,c[440][440],val[101000],dep[101000],head[101000],t[6],vis[101000],f[101000][440]; I Add(int &x,int y){ (x+=y)>=Mod?x-=Mod:0; } IN rnk(B a){ //cout<<mp[a]<<endl; if(!mp[a]){ cout<<"!"; F(i,0,4)cout<<a.b[i]<<" "; cout<<endl; system("pause"); } return mp[a]; re l=1,r=tot,mid; while(l<=r){ mid=(l+r)>>1; if(a==bas[mid])return mid; if(a<bas[mid])r=mid-1; else l=mid+1; } return mid; } IN Plus(B x,B y){ B tmp;C(tmp.b,0); memcpy(tmp.b,x.b,sizeof(tmp.b)); F(i,0,4){ if(!y.b[i])continue; if(!insert(tmp.b,y.b[i]))return 0; } return rnk(tmp); } I add(int x,int y,int w){ e[++sum].to=y;e[sum].nt=head[x];head[x]=sum;e[sum].w=w; } I D_1(int p,int w){ if(p==5){ tot++;F(i,0,4)bas[tot].b[i]=t[i];//,cout<<t[i]<<" "; //cout<<endl;system("pause"); return; } F(i,0,(1<<p)-1) if((w&i)==0){ t[p]=(1<<p)|i; D_1(p+1,w|(1<<p)); } t[p]=0; D_1(p+1,w); } inline bool bbb(B x,B y){ re ca=0,cb=0; F(i,0,4)ca+=(x.b[i]!=0),cb+=(y.b[i]!=0); return ca<cb; } I init(){ tot=0;D_1(0,0); sort(bas+1,bas+1+tot);F(i,1,tot)mp[bas[i]]=i; F(i,1,tot)F(j,1,tot)c[i][j]=Plus(bas[i],bas[j]); } I D_2(int x,int fa,int depth,int V){ val[x]=V;dep[x]=depth; for(re k=head[x];k!=-1;k=e[k].nt){ if(T==fa||vis[T]!=-1||T==1)continue; if(dep[T]&&dep[x]<dep[T])sn&=insert(now.b,val[x]^val[T]^e[k].w);//cout<<"loop"<<(val[x]^val[T]^e[k].w)<<endl; if(dep[T])continue; D_2(T,x,depth+1,V^e[k].w); } } I DP(int i,int rk){F(j,1,tot)Add(f[i][c[rk][j]],f[i-1][j]);}//F(j,1,tot)if(f[i][j])cout<<"!"<<rk<<" "<<i<<" "<<j<<endl;} int main(){ init();//cout<<tot<<endl; read(n);read(m);C(head,-1);sum=-1; F(i,1,m){ read(X);read(Y);read(W);add(X,Y,W);add(Y,X,W); } f[0][1]=1;C(vis,-1); for(re k=head[1];k!=-1;k=e[k].nt)vis[T]=e[k].w; cnt=0; F(i,2,n){ if(vis[i]==-1)continue;//cout<<"@"<<endl; C(now.b,0);X=0;W=0;cnt++;sn=1; for(re k=head[i];k!=-1;k=e[k].nt)if(vis[T]!=-1){ X=T;W=e[k].w;break; } D_2(i,0,1,0);if(X)D_2(X,0,1,0); DP(cnt,1); //cout<<"sn="<<sn<<endl; if(sn){ //F(i,0,4)cout<<now.b[i]<<" "; //cout<<endl; if(!X)DP(cnt,Y=rnk(now));//,cout<<Y<<endl; else{ DP(cnt,Y=rnk(now));DP(cnt,rnk(now));//cout<<Y<<endl; if(insert(now.b,vis[i]^vis[X]^W))DP(cnt,Y=rnk(now));//cout<<Y<<endl; } } vis[i]=vis[X]=-1; } ans=0; F(i,1,tot)Add(ans,f[cnt][i]); cout<<ans; return 0; }