分析
此题难点在于一些最小生成树的性质
可以参考这里
https://www.cnblogs.com/Y-E-T-I/p/8462255.html
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
#define id(x) wh[sf(x)]
const int mod = 31011;
struct node {
int x,y,z;
};
node d[1100];
inline bool cmp(const node a,const node b){
return a.z<b.z;
}
int fa[110],ffa[110],g[110][110],n,m,Ans,wh[110],cnt;
inline int sf(int x){return x==fa[x]?x:fa[x]=sf(fa[x]);}
inline int ssf(int x){return x==ffa[x]?x:ffa[x]=ssf(ffa[x]);}
inline int gs(){
int i,j,k,ans=1;
for(i=1;i<cnt;i++)
for(j=1;j<cnt;j++)
g[i][j]=(g[i][j]%mod+mod)%mod;
for(i=1;i<cnt;i++){
for(j=i;j<cnt;j++)
if(g[j][i])break;
if(j>=cnt){
puts("0");
exit(0);
}
if(j!=i)ans=mod-ans,swap(g[i],g[j]);
for(j=i+1;j<cnt;j++){
while(g[j][i]){
int t=g[i][i]/g[j][i];
for(k=i;k<cnt;k++)
g[i][k]=(g[i][k]-1ll*t*g[j][k]%mod+mod)%mod;
ans=mod-ans;
swap(g[i],g[j]);
}
}
ans=1ll*ans*g[i][i]%mod;
}
return ans;
}
int main(){
int i,j,k;
Ans=1;
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++)
scanf("%d%d%d",&d[i].x,&d[i].y,&d[i].z);
sort(d+1,d+m+1,cmp);
for(i=1;i<=n;i++)fa[i]=i,wh[i]=++cnt;
for(i=1;i<=m;i++){
memset(g,0,sizeof(g));
for(j=1;j<=cnt;j++)ffa[j]=j;
int _=i,sum=0;
while(_+1<=m&&d[_+1].z==d[_].z)_++;
for(j=i;j<=_;j++){
int x=d[j].x,y=d[j].y;
if(id(x)==id(y))continue;
g[id(x)][id(x)]++;
g[id(y)][id(y)]++;
g[id(x)][id(y)]--;
g[id(y)][id(x)]--;
if(ssf(id(x))!=ssf(id(y)))
sum++,ffa[ssf(id(x))]=ssf(id(y));
}
for(j=1;j<n;j++)
for(k=j+1;k<=n;k++)
if(ssf(id(j))!=ssf(id(k))){
g[id(j)][id(j)]++;
g[id(k)][id(k)]++;
g[id(j)][id(k)]--;
g[id(k)][id(j)]--;
ffa[ssf(id(j))]=ssf(id(k));
}
if(!sum){
i=_;
continue;
}
Ans=1ll*Ans*gs()%mod;
cnt=0;
for(j=i;j<=_;j++){
int x=d[j].x,y=d[j].y;
if(sf(x)!=sf(y))fa[sf(x)]=sf(y);
}
memset(wh,0,sizeof(wh));
for(j=1;j<=n;j++)
if(!id(j))id(j)=++cnt;
i=_;
if(cnt==1)break;
}
if(cnt>1)puts("0");
else printf("%d
",Ans);
return 0;
}