你知道黑暗城堡有N個房間(1≤N≤1000),M條能夠製造的雙向通道,以及每條通道的長度。
城堡是樹形的而且知足下面的條件:若是全部的通道都被修建,設D[i]爲第i號房間與第1號房間的最短路徑長度;而S[i]爲實際修建的樹形城堡中第i號房間與第1號房間的路徑長度;要求對於全部整數i(1≤i≤N),有S[i]=D[i]成立。
你想知道有多少種不一樣的城堡修建方案。固然,你只須要輸出答案對231-1取模以後的結果就好了。
4 6
1 2 1
1 3 2
1 4 3
2 3 1
2 4 2
3 4 1
6
最短路徑樹SPT(Short Path Tree)是網絡的源點到全部結點的最短路徑構成的樹。那麼本題就是相求有多少顆以1爲源點的最短路徑樹。那麼能夠先求出每一個點的入邊中,有多少條是最短路徑上的邊,再考慮按照最短路徑大小升序依次訪問這些點,當咱們訪問到某種狀態時,須要拓展下一個點,那麼這個點的入邊在最短路徑上的邊均可以成爲咱們拓展的邊,因而答案乘上這個邊數。
#include<bits/stdc++.h> using namespace std; const int N =1005; const long long mod=(1ll<<31) - 1; struct ss { int u,v,w,next; }; ss edg[N*N]; int head[N],sum_edge=0; void addedge(int u,int v,int w) { edg[sum_edge]=(ss){u,v,w,head[u]}; head[u]=sum_edge++; } priority_queue<pair<long long,int> >q; int vis[N]={0}; long long dis[N]; void dij(int S) { for(int i=0;i<N;i++)dis[i]=LLONG_MAX/2; dis[S]=0; q.push(make_pair(0,S)); while(q.size()) { int x=q.top().second; q.pop(); if(vis[x])continue; vis[x]=1; for(int i=head[x];i!=-1;i=edg[i].next) { int v=edg[i].v; if(dis[v]>dis[x]+edg[i].w) { dis[v]=dis[x]+edg[i].w; q.push(make_pair(-dis[v],v)); } } } } int main() { memset(head,-1,sizeof(head)); int n,m; scanf("%d %d",&n,&m); while(m--) { int u,v,w; scanf("%d %d %d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } dij(1); long long ans=1; long long cnt[N]={0}; pair<long long ,int >arr[N]; for(int i=1;i<=n;i++) { arr[i].first=dis[i]; arr[i].second=i; } sort(arr+1,arr+1+n); for(int i=1;i<=n;i++) { int x=arr[i].second; for(int j=head[x];j!=-1;j=edg[j].next) { int v=edg[j].v; if(dis[v]==dis[x]+edg[j].w)cnt[v]++; } ans*=max(cnt[x],1ll); ans%=mod; } printf("%lld\n",ans); return 0; }