给你一个图,问你有几种最短路径树(最短路径树:满足每个点到根节点的距离等于原图中的最短路的生成树)
最短路径树的构造:(1)跑一次DIJ(2)假如对于边(u,v,w)dis[u]=dis[v]+w则当前路可以加入最短路径树中
因为我们要保证到每个点的距离最小,所以我们其实只能用相同的权值替换当前最短路径树上的边,然后运用乘法原理相乘即可
而且这种关系是单向的dis[u]=dis[v]+w就不会出现dis[v]=dis[u]+w,不用担心出现多加的情况
struct Graph
{
int tot,head[1111];
struct IN{int v,next,w;}edge[MX<<1];
void init(){memset(head,-1,sizeof(head));tot=0;}
void addedge(int u,int v,int w)
{
edge[tot].v=v;edge[tot].w=w;
edge[tot].next=head[u];head[u]=tot++;
}
int Start(int u){return head[u];}
int To(int i){return edge[i].v;}
int Val(int i){return edge[i].w;}
int Next(int i){return edge[i].next;}
}G;
int n,m,s;
int dis[1111],vis[1111];
void input()
{
cin>>n>>m;
s=1;
G.init();
for(int i=0;i<m;i++)
{
int u,v,w;cin>>u>>v>>w;
G.addedge(u,v,w);
G.addedge(v,u,w);
}
}
void dij(int x)//x=start
{
priority_queue<pii > q;// 第一关键字为距离,第二关键字为点
memset(dis,0x3f3f3f3f,sizeof(dis));
memset(vis,0,sizeof(vis));
q.push(make_pair(0,x));
dis[x]=0;
while(q.size())
{
int u=q.top().second;
q.pop();
if (vis[u]) continue;
vis[u]=1;
for (int i=G.Start(u);~i;i=G.Next(i))
{
int v=G.To(i);
if (dis[v]>dis[u]+G.Val(i))
{
dis[v]=dis[u]+G.Val(i);
q.push(make_pair(-dis[v],v));
}
}
}
}
int cnt[1111];
signed main()
{
input();
dij(s);
rpp(_,n)
{
for(int i =G.Start(_);~i;i=G.Next(i))
{
int v=G.To(i);
if(dis[v]==dis[_]+G.Val(i)) ++cnt[v];
}
}
ll ans=1;
rpp(i,n) if(cnt[i]) ans=ans*cnt[i]%(2147483647);
cout<<ans<<endl;
stop;
return 0;
}