My God, it took another night to fix it. One of the subtle logical errors is that when we do the minimal spanning tree to keep and collect the state by the way, whether or not we deal with the edges of the new species (after discretization), we should first copy fa into nowfa, otherwise there will be an edge that has not been used (because it will form a ring after joining). The corresponding nowfa are all 0, which leads to the conclusion that the number of alternatives is zero when dfs judges whether the selected edge will form a ring (because fa[a], fa[b] are all 0).
#include<bits/stdc++.h> #define rep(i,l,r) for(int i=(l);i<=(r);i++) #define per(i,r,l) for(int i=(r);i>=(l);i--) using namespace std; typedef long long ll; const int inf=1e9+10,mod=31011,N=666,M=2222; const double eps=1e-6; struct edge{ int a,b,w; bool friend operator < (edge a,edge b){ return a.w<b.w; } }e[M]; int n,m,cnt[M],fa[N];//cnt[i] denotes that the edges of weight ranking I are used in the minimum spanning tree. int nowfa[M][N],st[N],ret; ll ans=1; int getf(int v){ return fa[v]==v?v:fa[v]=getf(fa[v]);} bool selected[M]; int tmpfa[N]; int tmpgetf(int v) { return tmpfa[v]==v?v:tmpfa[v]=tmpgetf(tmpfa[v]);} void dfs(int v,int pos,int sel){ if(sel==cnt[v]){ memcpy(tmpfa,nowfa[v-1],sizeof(nowfa[v-1])); rep(i,st[v],pos) if(selected[i]){ int faa=tmpgetf(e[i].a),fab=tmpgetf(e[i].b); if(faa==fab) return; tmpfa[fab]=faa; } ret++; return; } if(pos>=st[v+1])return; dfs(v,pos+1,sel); selected[pos]=true; dfs(v,pos+1,sel+1); selected[pos]=false; } void process(int v){ ret=0; if(cnt[v]==0) return; dfs(v,st[v],0); ans=(ans*(ll)ret)%mod; return; } int main(){ ios::sync_with_stdio(false); cin.tie(0); cin>>n>>m; rep(i,1,m) cin>>e[i].a>>e[i].b>>e[i].w; sort(e+1,e+1+m); int now=0,num=0; rep(i,1,m){//Discrete Processing if(e[i].w!=now){ now=e[i].w; e[i].w=++num; st[e[i].w]=i; }else e[i].w=num; } st[e[m].w+1]=m+1; rep(i,1,n) fa[i]=i; int last=0,tot=0; rep(i,1,m){ int faa=getf(e[i].a),fab=getf(e[i].b); memcpy(nowfa[last],fa,sizeof(fa)); last=e[i].w; if(faa==fab) continue; cnt[e[i].w]++; fa[fab]=faa; tot++; } if(tot<n-1){ cout<<0; return 0; } rep(i,1,num) process(i);//Processing edges with weights i cout<<ans; return 0; }