求助
  • 板块灌水区
  • 楼主ZS_伪装aba
  • 当前回复4
  • 已保存回复4
  • 发布时间2020/11/30 18:01
  • 上次更新2023/11/5 07:01:53
查看原帖
求助
390603
ZS_伪装aba楼主2020/11/30 18:01

大佬帮看一下,老师让我们照着可以理解的题解打一篇(这道题对蒟蒻来说有点难) 为什么只有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);
 } 
2020/11/30 18:01
加载中...