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;
}
View Code

 

posted @ 2017-10-25 00:42  新手-周  阅读(...)  评论(... 编辑 收藏