题目描述】
知道黑暗城堡有 N 个房间,M 条可以制造的双向通道,以及每条通道的长度。
城堡是树形的并且满足下面的条件:
设 Di 为如果所有的通道都被修建,第 i号房间与第 1 号房间的最短路径长度;
而 Si 为实际修建的树形城堡中第 i 号房间与第 1 号房间的路径长度;
要求对于所有整数 i(1≤i≤N) ,有 Si=Di 成立。
你想知道有多少种不同的城堡修建方案。当然,你只需要输出答案对 231−1231−1 取模之后的结果就行了。
【输入】
第一行为两个由空格隔开的整数 N,MN,M ;
第二行到第 M+1行为 3 个由空格隔开的整数 x,y,l :表示 x 号房间与 y 号房间之间的通道长度为 l 。
【输出】
一个整数:不同的城堡修建方案数对 231−1231−1 取模之后的结果。
【输入样例】
4 6
1 2 1
1 3 2
1 4 3
2 3 1
2 4 2
3 4 1
【输出样例】
6
最终形成的路径一定是最短的。先用迪杰斯特拉求出求短路径dis数组,再dis[i]=dis[j]+c[j][i],cnt++;记录每个i可以有多少条路径,最后在相乘。
#include<stdio.h>
#include<math.h>
#include<algorithm>
const long long N=pow(2,31)-1;
using namespace std;
int inf=0x3f3f3f3f;
const int K=6e3;
int c[K][K],n,m;
int dis[K];
int book[K];
void memset()
{
int i,j;
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
if(i==j)
c[i][j]=0;
else
c[i][j]=inf;
}
}
void djk()
{
int i,k=m,j;
for(i=1; i<=n; i++)
dis[i]=c[1][i];
dis[1]=0;
book[1]=1;
while(k--)
{
int u,minn=inf;
for(i=1; i<=n; i++)
{
if(dis[i]<minn&&book[i]==0)
{
u=i;
minn=dis[i];
}
}
book[u]=1;
for(j=1; j<=n; j++)
{
if(c[u][j]<inf)
{
if(dis[j]>dis[u]+c[u][j]&&i!=j)
{
dis[j]=dis[u]+c[u][j];
}
}
}
}
}
int main()
{
int i,j;
scanf("%d %d",&n,&m);
memset();
for(i=0; i<m; i++)
{
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
if(c[x][y]>z)
c[x][y]=c[y][x]=z;
}
djk();
long long ans=1,cnt=0;
for(i=2; i<=n; i++)
{
cnt=0;
for(j=1; j<=n; j++)
{
if(dis[j]+c[j][i]==dis[i])
cnt++;
}
ans=(ans*cnt)%N;
}
printf("%lld\n",ans);
}