在顺利攻破Lord lsp的防线之后,lqr一行人来到了Lord lsp的城堡下方。Lord lsp黑化之后虽然拥有了强
大的超能力,能够用意念力制造建筑物,但是智商水平却没怎么增加。现在lqr已经搞清楚黑暗城堡有N个房间
,M条可以制造的双向通道,以及每条通道的长度。lqr深知Lord lsp的想法,为了避免每次都要琢磨两个房间
之间的最短路径,Lord lsp一定会把城堡修建成树形的;但是,为了尽量提高自己的移动效率,Lord lsp一定会
使得城堡满足下面的条件:设Di为如果所有的通道都被修建,第i号房间与第1号房间的最短路径长度;而Si
为实际修建的树形城堡中第i号房间与第1号房间的路径长度,对于所有满足1≤i≤N的整数i,有Si=Di
。为了打败Lord lsp,lqr想知道有多少种不同的城堡修建方案。于是lqr向applepi提出了这个问题。由于a
pplepi还要忙着出模拟赛,所以这个任务就交给你了。当然,你只需要输出答案对2^31–1取模之后的结果就
行了.
Input
第一行有两个整数N和M。
之后M行,每行三个整数X,Y和L,表示可以修建X和Y之间的一条长度为L的通道。
2≤N≤1000,N–1≤M≤N(N–1)/2,1≤L≤100
Output
输出一个整数,表示答案对2^31–1取模之后的结果。
Sample Input
3 3
1 2 2
1 3 1
2 3 1
Sample Output
2
Sol:跑一次最短路,同时记下从1出发到每个点的最短图,并统计出有多少条。在构建后面的最短路径树时,乘起来就好了。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<map> #include<queue> #include<set> #define ll long long #define llu unsigned ll using namespace std; const int mod=(1ll<<31)-1; const int maxn=1000100; const int maxx=1200; const int inf=0x3f3f3f3f; int head[maxx],edge[maxn],ver[maxn],nt[maxn]; int d[maxx]; int ha[maxx]; int cnt[maxx]; int tot=1,n,m; void add(int x,int y,int z) { ver[++tot]=y,edge[tot]=z; nt[tot]=head[x],head[x]=tot; } void Dij(void) { memset(d,0x3f,sizeof(d)); memset(ha,0,sizeof(ha)); d[1]=0; priority_queue<pair<int,int> >q; q.push(make_pair(0,1)); while(q.size()) { int x=q.top().second; q.pop(); if(ha[x]) continue; ha[x]=true; for(int i=head[x];i;i=nt[i]) { int y=ver[i],z=edge[i]; if(d[y]>d[x]+z) //更新最短路 { d[y]=d[x]+z; cnt[y]=1;//从出发点到y的最短路有1条了 q.push(make_pair(-d[y],y)); } else if(d[y]==d[x]+z)//找到另一条到y的最短路 { cnt[y]++; } } } return ; } int main(void) { scanf("%d%d",&n,&m); int x,y,z; for(int i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z); } Dij(); cnt[1]=1; ll ans=1; for(int i=1;i<=n;i++) { //cout<<i<<" "<<cnt[i]<<endl; ans=ans*cnt[i]%mod; } printf("%lld\n",ans); return 0; }
input
5 7
1 2 1
1 3 2
1 4 1
2 3 1
4 3 1
3 5 2
4 5 3
output
6