一本通 1486:【例题1】黑暗城堡 题解
题目描述
知道黑暗城堡有 N 个房间,M 条可以制造的双向通道,以及每条通道的长度。
城堡是树形的并且满足下面的条件:
设 Di为如果所有的通道都被修建,第 i 号房间与第 1 号房间的最短路径长度;
而 Si 为实际修建的树形城堡中第 i 号房间与第 1 号房间的路径长度;
要求对于所有整数 i(1≤i≤N),有 Si=Di 成立。
你想知道有多少种不同的城堡修建方案。当然,你只需要输出答案对 2的31次方-1 取模之后的结果就行了。
输入格式
第一行为两个由空格隔开的整数 N,M;
第二行到第 M+1 行为 3 个由空格隔开的整数 x,y,l:表示 x 号房间与 y 号房间之间的通道长度为 l。
输出格式
一个整数:不同的城堡修建方案数对 2的31次方-1 取模之后的结果。
AC代码
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 ll n,m,d[2020],dis[2020][2020],x,y,z,cnt[20020]; 5 bool vis[2000010]; 6 int main() 7 { 8 scanf("%lld%lld",&n,&m); 9 for (int i=1;i<=n;i++) 10 for (int j=1;j<=n;j++) 11 if (i==j) dis[i][j]=0; 12 else dis[i][j]=1e18; 13 for (int i=1;i<=m;i++) 14 { 15 scanf("%lld%lld%lld",&x,&y,&z); 16 if (dis[x][y]>z) 17 { 18 dis[x][y]=z; 19 dis[y][x]=z; 20 } 21 } 22 for (int i=1;i<=n;i++) 23 d[i]=dis[1][i]; 24 for (int i=1;i<=n;i++) 25 { 26 ll minn=1e18,k; 27 for (int j=1;j<=n;j++) 28 { 29 if (!vis[j]&&minn>d[j]) 30 { 31 minn=d[j]; 32 k=j; 33 } 34 } 35 vis[k]=1; 36 for (int j=1;j<=n;j++) 37 if (d[j]>d[k]+dis[k][j]) 38 d[j]=d[k]+dis[k][j]; 39 } 40 for (int i=1;i<=n;i++) 41 for (int j=1;j<=n;j++) 42 if (i!=j&&d[j]==d[i]+dis[i][j]) 43 cnt[j]++; 44 ll ans=1; 45 for (int i=1;i<=n;i++) 46 if (cnt[i]) 47 { 48 ans*=cnt[i]; 49 ans%=2147483647; 50 } 51 printf("%lld\n",ans); 52 return 0; 53 }