黑暗城堡
黑暗城堡
时间限制: 1 Sec 内存限制: 128 MB题目描述
你知道黑暗城堡有N个房间(1≤N≤1000),M条可以制造的双向通道,以及每条通道的长度。
城堡是树形的并且满足下面的条件:如果所有的通道都被修建,设D[i]为第i号房间与第1号房间的最短路径长度;而S[i]为实际修建的树形城堡中第i号房间与第1号房间的路径长度;要求对于所有整数i(1≤i≤N),有S[i]=D[i]成立。
你想知道有多少种不同的城堡修建方案。当然,你只需要输出答案对231-1取模之后的结果就行了。
城堡是树形的并且满足下面的条件:如果所有的通道都被修建,设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; }
路漫漫其修远兮,吾将上下而求索