标签:span 一点 判断 jks 点距 最短路径 void return 需要
??给出一张图,求它最短路径树的个数。
??最短路径树就是对于根节点\(u\),它到任意\(v\)的最小距离等于树上的距离。我们考虑\(dijkstra\)的过程,每一次选择一个与起始节点距离最小的点加入已确定的集合,所以我们每次选择的边组成的集合就是一种最短路径树。至于统计方案,在进行\(dijkstra\)的时候,我们可以判断每一条边,如果\(dis[v]=dis[u]+e[i]\)方案数可以累乘,不过如果更新\(dis\)需要重置到这一点的最短路方案数。当然我们也可以在跑完\(dijkstra\)后统计答案。
#include <bits/stdc++.h>
using namespace std;
const long long mod=2147483647;
const int MAXN=1005,MAXM=5e5+10;
int head[MAXN],nxt[MAXM*2],to[MAXM*2],w[MAXM*2],tot;
int dis[MAXN];
bool vis[MAXN];
void add_edge(int x,int y,int z)
{
nxt[++tot]=head[x];
head[x]=tot;
to[tot]=y;
w[tot]=z;
}
priority_queue<pair<int,int> >q;
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add_edge(x,y,z);
add_edge(y,x,z);
}
memset(dis,0x3f,sizeof(dis));
dis[1]=0;
q.push(make_pair(0,1));
while(!q.empty())
{
int x=q.top().second;q.pop();
if(vis[x])continue ;
vis[x]=1;
for(int i=head[x];i;i=nxt[i])
{
int y=to[i],v=w[i];
if(dis[y]>dis[x]+v)
{
dis[y]=dis[x]+v;
q.push(make_pair(-dis[y],y));
}
}
}
/* for(int i=1;i<=n;i++)
printf("%d ",dis[i]);
printf("\n");*/
long long ans=1;
for(int i=1;i<=n;i++)
{
long long s=0;
for(int j=head[i];j;j=nxt[j])
{
int k=to[j],v=w[j];
if(dis[i]==dis[k]+v)
s++;
}
// cout<<s<<' '<<ans<<endl;
if(s!=0)ans=(ans*s)%mod;
}
printf("%lld\n",ans);
return 0;
}
标签:span 一点 判断 jks 点距 最短路径 void return 需要
原文地址:https://www.cnblogs.com/fangbozhen/p/11794835.html