城堡
问题描述:
给定一张n个点m条边的无向连通图,每条边有边权。我们需要从m条边中
选出n−1条,构成一棵树。记原图中从 1 号点到每个节点的最短路径长度为di,树中从 1 号点到每个节点的最短路径长度为? ? ,构出的树应当满足对于任意节点si,都有di=si。
请你求出选出n−1条边的方案数。
输入格式:
输入的第一行包含两个整数n和m。
接下来m行,每行包含三个整数u、v和w,描述一条连接节点u和v且边权为
w的边。
输出格式:
输出一行,包含一个整数,代表方案数对2^31−1取模得到的结果。
样例输入:
3 3
1 2 2
1 3 1
2 3 1
样例输出:
2
数据规模和约定:
对于30%的数据2 ≤n≤ 5,m≤ 10。
对于50%的数据,满足条件的方案数不超过 10000。
对于100%的数据,2≤n≤ 1000,n− 1≤m≤n*(n−1)/2,1≤w≤100。
#include<iostream>
#include<cstdio>
#include<queue>
#define lon long long
using namespace std;
const int maxn=10010;
const long long mod=0x7fffffff;
lon n,m,tot,c[maxn],head[maxn],dis[maxn];
bool flag[maxn];
struct node
{
lon to;
lon from;
lon w;
lon next;
}e[1000010];
lon init()
{
lon x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
void add_edge(lon u,lon v,lon w)
{
e[++tot].to=v;
e[tot].from=u;
e[tot].w=w;
e[tot].next=head[u];
head[u]=tot;
}
void spfa()
{
for(lon i=1;i<=n;i++)
dis[i]=0x7fffffff;dis[1]=0;
queue<lon> q;
q.push(1);flag[1]=1;
while(!q.empty())
{
lon u=q.front();
q.pop();flag[u]=0;
for(lon i=head[u];i;i=e[i].next)
{
lon v=e[i].to;
if(dis[v]>dis[u]+e[i].w)
{
dis[v]=dis[u]+e[i].w;
if(!flag[v])
{
q.push(v);
flag[v]=1;
}
}
}
}
}
int main()
{
freopen("castle.in","r",stdin);
freopen("castle.out","w",stdout);
lon x,y,z;
n=init();m=init();
for(lon i=1;i<=m;i++)
{
x=init();y=init();z=init();
add_edge(x,y,z);
add_edge(y,x,z);
}
spfa();
lon ans=1;
for(int i=1;i<=tot;i++)
{
lon u=e[i].from;
lon v=e[i].to;
if(dis[v]==dis[u]+e[i].w)
c[v]++;
}
for(int i=2;i<=n;i++)
ans=(ans*c[i])%mod;
cout<<ans;
fclose(stdin);fclose(stdout);
return 0;
}