题目描述
你知道黑暗城堡有 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 取模之后的结果。
样例
样例输入
4 6
1 2 1
1 3 2
1 4 3
2 3 1
2 4 2
3 4 1
样例输出
6
样例说明
一共有 4 个房间,6 条道路,其中 1 号和 2 号,1 号和 3 号,1 号和 4 号,2 号和 3 号,2 号和 4 号,3 号和 4 号房间之间的通道长度分别为 1,2,3,1,2,1。
而不同的城堡修建方案数对 2^{31} -1 取模之后的结果为 6。
数据范围与提示
对于全部数据,1≤N≤1000,1≤M≤N(N−1)/2,1≤l≤200。
——————————————————————————————————————————
这是一道很神的题。
首先dij,求出1号点到其他点的最短距离。
然后扫描所有边,如果dis[v]==dis[u]+e[i].w,说明让v点的距离为给最短距离的路径又多了一条,所以,cnt[v]++;
最终结果就是所有点的cnt[]相乘。
!!!!!!!!!!!!
。。。。。。。。。。。。。。。
——————————————————————————————————————————
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 long long mod=((long long)1<<31)-1; 4 const int maxn=1010; 5 const int maxm=5e5; 6 int n,m; 7 struct edge 8 { 9 int u,v,w,nxt; 10 }e[maxm<<1]; 11 int head[maxn],js; 12 void addage(int u,int v,int w) 13 { 14 e[++js].u=u;e[js].v=v;e[js].w=w; 15 e[js].nxt=head[u];head[u]=js; 16 } 17 int dis[maxn]; 18 bool vis[maxn]; 19 struct node 20 { 21 int dis,p; 22 bool operator < (node b)const 23 { 24 return dis>b.dis; 25 } 26 }; 27 priority_queue< node > q; 28 void dij() 29 { 30 memset(dis,0x7f,sizeof(dis)); 31 dis[1]=0; 32 q.push((node){0,1}); 33 while(!q.empty()) 34 { 35 node tp=q.top(); 36 q.pop(); 37 int u=tp.p; 38 if(vis[u])continue; 39 vis[u]=1; 40 for(int i=head[u];i;i=e[i].nxt) 41 { 42 int v=e[i].v; 43 if(dis[u]+e[i].w<dis[v]) 44 { 45 dis[v]=dis[u]+e[i].w; 46 q.push((node){dis[v],v}); 47 } 48 } 49 } 50 } 51 int cnt[maxn]; 52 long long ans=1; 53 int main() 54 { 55 scanf("%d%d",&n,&m); 56 for(int u,v,w,i=0;i<m;++i) 57 { 58 scanf("%d%d%d",&u,&v,&w); 59 addage(u,v,w);addage(v,u,w); 60 } 61 dij(); 62 for(int j=1;j<=n;++j) 63 for(int i=head[j];i;i=e[i].nxt) 64 if(dis[e[i].v]==dis[e[i].u]+e[i].w)cnt[e[i].v]++; 65 for(int i=2;i<=n;++i)ans=ans*cnt[i]%mod; 66 cout<<ans; 67 return 0; 68 }