大佬帮看一下,老师让我们照着可以理解的题解打一篇(这道题对蒟蒻来说有点难) 为什么只有50分?
#include<bits/stdc++.h>
using namespace std;
struct node{
int x,y,z;
}a[1001],b[1001];
int n,m,t,ro[1001],d[1001],c[1001],cnt,ans,fx,fy;
int find(int x)//并查集的查询,使祖先为同一个
{
if(ro[x]==x)
return x;
ro[x]=find(ro[x]);
return ro[x];
}
void dfs(int now,int k,int x)
//now表示当前位置,k表示加入边数,x表示权值种类在d数组中位置
{
if(now>b[x].y)//如果搜过右端点
{
if(k==d[x])
cnt++;//符合情况则+1
return;
}
int p[101];
for(int i=1;i<=n;i++)
{
p[i]=ro[i];
}
fx=find(a[now].x);
fy=find(a[now].y);
if(fx!=fy)
{
ro[fx]=fy;
dfs(now+1,k+1,x);
}
for(int i=1;i<=n;i++)
{
ro[i]=p[i];
}
dfs(now+1,k,x);
}
int cmp(node a,node b)
{
return a.z<b.z;
}
void readd()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
}
int main()
{
//readd();
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d %d %d",&a[i].x,&a[i].y,&a[i].z);
sort(a+1,a+1+m,cmp);
for(int i=1;i<=n;i++)
{
ro[i]=i;//初始化
}
a[0].z=-INT_MAX;//INT_MAX是一个极大值
t=0;
for(int i=1;i<=m;i++)
{
if(a[i].z==a[i-1].z)//搜索由同一权值的边的左右位置
{
b[t].y++;
c[i]=t;
}
else
{//x表示左端点,t表示权值种数
t++;
b[t].x=i;
b[t].y=i;
c[i]=t;
}
}
cnt=0;
for(int i=1;i<=m;i++)
{
fx=find(a[i].x);
fy=find(a[i].y);
//找最小生成树
if(fx!=fy)
{
ro[fx]=fy;
d[c[i]]++;
//d存储该权值要多少条边
cnt++;
}
if(cnt==n-1)//如果找到了最小生成树
//cnt是已经找的边数,n-1是总共的边数
break;
}
if(cnt!=n-1)
{
printf("0");
exit(0);//终止程序
}
for(int i=1;i<=t;i++) //t表示权值种数
{
ro[i]=i;
}
ans=1;
for(int i=1;i<=t;i++)
{
if(d[i]>0)//如果有权值为i的边
{
cnt=0;
dfs(b[i].x,0,i);
// i刚好是在d数组的位置
ans=(ans*cnt)%31011;
//输出不同的最小生成树有多少个
//你只需要输出数量对31011的模就可以了。
for(int j=b[i].x;j<=b[i].y;j++)
{//更新
fx=find(a[j].x);
fy=find(a[j].y);
if(fx!=fy)
{
ro[fx]=fy;
}
}
}
}
printf("%d\n",ans);
}