这题题目中有一个很显眼的提示,每种权值的边不会超过10条,这提示我们可以采用些暴力方法。
首先在每个最小生成树中有两个结论:
1、每种权值的边数相等。
2、每种权值所选边构建后图的联通形态相同。
1比较好理解,若1不成立,则最小生成树总权值不固定。
2可以通过Kruskal算法流程来理解。
code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct hq{
int sum;
int num[1001];
}stack[1001],tot[1001];
struct hp{
int u,v,w;
}a[1001];
int father[1001],now[1001],fathernow[1001],fatherlast[1001];
int b[1001],n,m,size,sum=0,t=0,ans=1;
int cmp(const hp &a,const hp &b)
{
if (a.w<b.w) return 1;
else return 0;
}
int findnow(int x)
{
if (x!=fathernow[x])
fathernow[x]=findnow(fathernow[x]);
return fathernow[x];
}
int find(int x)
{
if (x!=father[x])
father[x]=find(father[x]);
return father[x];
}
bool judge()
{
int i,r1,r2;
bool f=false;
for (i=1;i<=n;++i)
fathernow[i]=fatherlast[i];
for (i=1;i<=t;++i)
{
r1=findnow(a[now[i]].u);
r2=findnow(a[now[i]].v);
if (r1<r2)
fathernow[r1]=fathernow[r2];
else
{
if (r2<r1)
fathernow[r2]=fathernow[r1];
else
f=true;
}
}
for (i=1;i<=n;++i)
findnow(i),find(i);
for (i=1;i<=n;++i)
if (fathernow[i]!=father[i])
f=true;
for (i=1;i<=n;++i)
fathernow[i]=fatherlast[i];
if (f)
return false;
else
return true;
}
void work(int wgt,int i,int last)
{
int j;
if (i==tot[wgt].sum+1)
{
if (judge())
sum=(sum+1)%31011;
return;
}
for (j=last+1;j<=stack[wgt].sum;++j)
{
now[++t]=stack[wgt].num[j];
work(wgt,i+1,j);
--t;
}
}
int main()
{
int i,r1,r2,j,k=0,wgt=0;
scanf("%d%d",&n,&m);
for (i=1;i<=m;++i)
{
scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
b[i]=a[i].w;
}
sort(b+1,b+m+1);
size=unique(b+1,+b+m+1)-b-1;
for (i=1;i<=m;++i)
a[i].w=upper_bound(b+1,b+size+1,a[i].w)-b-1;
sort(a+1,a+m+1,cmp);
for (i=1;i<=m;++i)
stack[a[i].w].num[++stack[a[i].w].sum]=i;
for (i=1;i<=n;++i)
father[i]=i;
for (i=1;i<=m;++i)
{
r1=find(a[i].u); r2=find(a[i].v);
if (r1!=r2)
{
tot[a[i].w].num[++tot[a[i].w].sum]=i;
wgt+=a[i].w;
father[r1]=r2;
k++;
size=a[i].w;
}
if (k==n-1)
break;
}
if (k!=n-1)
printf("0\n");
else
{
for (i=1;i<=n;++i)
father[i]=fatherlast[i]=i;
for (i=1;i<=size;++i)
{
for (j=1;j<=tot[i].sum;++j)
{
r1=find(a[tot[i].num[j]].u);
r2=find(a[tot[i].num[j]].v);
if (r1<r2)
father[r1]=father[r2];
if (r2<r1)
father[r2]=father[r1];
}
memset(now,0,sizeof(now));
t=0; sum=0;
work(i,1,0);
ans=(ans*sum)%31011;
for (j=1;j<=n;++j)
fatherlast[j]=father[j];
}
printf("%d\n",ans);
}
}
时间: 2024-11-01 06:22:32