1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
| #include <cstdio> #include <cstring> #include <cmath> #include <algorithm>
using std::sort; using std::swap; using std::fabs;
const int P=31011; const int maxn=(1e3+100)*2; const double eps=1e-6;
bool used[maxn];
namespace MST { int fa[maxn]; int u[maxn],v[maxn],w[maxn],r[maxn],tot; long double K[maxn][maxn]; inline int find(int u){return u==fa[u]?u:fa[u]=find(fa[u]);} inline void add(int _u,int _v,int _w){u[++tot]=_u,v[tot]=_v,w[tot]=_w;} struct cmp{bool operator() (const int a,const int b){return w[a]<w[b];}}; inline long double determinant(long double (*A)[maxn],int n) { for (int i=1,c=1,j;i<=n;++i) { for (j=c;j<=n && fabs(A[j][i])<eps;++j); if (j==n+1) continue; for (int k=1;k<=n;++k) swap(A[c][k],A[j][k]); for (int j=c+1;j<=n;++j) if (fabs(A[j][i])>eps) { long double t=A[j][i]/A[c][i]; for (int k=i;k<=n;++k) A[j][k]-=A[c][k]*t; } ++c; } long double ans=1; for (int i=1;i<=n;++i) ans*=A[i][i]; return fabs(ans); } inline void Kruskal(int n,int m) { for (int i=1;i<=n;++i) fa[i]=i; for (int i=1;i<=m;++i) r[i]=i; sort(r+1,r+m+1,cmp()); for (int i=1;i<=m;++i) { int x=r[i]; if (find(u[x])!=find(v[x])) { fa[find(u[x])]=find(v[x]); used[x]=true; } } } int index[maxn]; inline void Add_edge(int idx) { int x=index[find(u[idx])],y=index[find(v[idx])]; ++K[x][x];++K[y][y]; --K[x][y];--K[y][x]; } inline void merge(int idx) { if (find(u[idx])!=find(v[idx])) fa[find(u[idx])]=find(v[idx]); } inline int Build_Graph(int n,int m,int L,int R) { int tot=0; for (int i=1;i<=n;++i) for (int j=1;j<=n;++j) K[i][j]=0; for (int i=1;i<=n;++i) fa[i]=i; for (int i=1;i<=m;++i) if (used[r[i]] && (i<L || i>R)) merge(r[i]); memset(index,0,sizeof(index)); for (int i=1;i<=n;++i) if (!index[find(i)]) index[find(i)]=++tot; for (int i=L;i<=R;++i) Add_edge(r[i]); return tot; } inline int Kruskal_cal(int n,int m) { int ans=1; for (int L=1,R=1;R<=m;L=R) { bool ok=false; while (w[r[L]]==w[r[R]] && R<=m) if (used[r[R++]]) ok=true; if (!ok) continue; int tot=Build_Graph(n,m,L,R-1); ans=((long long)ans*(int)std::round(determinant(K,tot-1)))%P; } return ans; } }
int main() { int n,m; scanf("%d%d",&n,&m); for (int i=1,u,v,w;i<=m;++i) scanf("%d%d%d",&u,&v,&w),MST::add(u,v,w); MST::Kruskal(n,m); printf("%d",MST::Kruskal_cal(n,m)); }
|