bzoj1016
这是一道对我而言很玄学的题
先求出最小生成树,然后暴力dfs统计等价值的边的个数,乘法原理.
#include <stdio.h> #include <algorithm> #include <cstring> #include <cmath> #include <queue> #include <vector> using namespace std; const int lxn=31011; struct hh { int u,v,w; }e[1005]; struct fuck { int l,r,v; }a[1005]; int n,m,cnt,tot,ans=1,sum; int fa[105]; template <class T> void read(T&x) { x=0;char c=getchar();int f=0; while(c<'0'||c>'9'){f|=(c=='-');c=getchar();} while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^=48),c=getchar(); x=f?-x:x; } bool cmp(const hh&a,const hh&b){return a.w<b.w;} int find(int v){return fa[v]==v?v:find(fa[v]);} void dfs(int x,int now,int k) { if(now==a[x].r+1) { if(k==a[x].v)sum++; return; } int p=find(e[now].u),q=find(e[now].v); if(p!=q) { fa[p]=q; dfs(x,now+1,k+1); fa[p]=p;fa[q]=q; } dfs(x,now+1,k); } int main() { read(n);read(m); for(register int i=1;i<=n;i++)fa[i]=i; for(register int i=1;i<=m;i++)read(e[i].u),read(e[i].v),read(e[i].w); sort(e+1,e+1+m,cmp); for(int i=1;i<=m;i++) { if(e[i].w!=e[i-1].w){a[++cnt].l=i;a[cnt-1].r=i-1;} int p=find(e[i].u),q=find(e[i].v); if(p!=q){fa[p]=q;a[cnt].v++;tot++;} } a[cnt].r=m; if(tot!=n-1){printf("0");return 0;} for(int i=1;i<=n;i++)fa[i]=i; for(int i=1;i<=cnt;i++) { sum=0; dfs(i,a[i].l,0); ans=(ans*sum)%lxn; for(int j=a[i].l;j<=a[i].r;j++) { int p=find(e[j].u),q=find(e[j].v); if(p!=q)fa[p]=q; } } printf("%d",ans); return 0; }