题目大意:
题目链接:https://www.luogu.org/problemnew/show/P1144
求一个无向无权图的1号点到每个点最短路的个数。
思路:
一开始看到这道题真的蒙了。。。
现在看回来才发现十分简单。其实就是一个SPFA的模板。但是为了“计数”,可以开一个记录答案的数组
s
u
m
sum
sum,那么如果又找到一条从点1到点
i
i
i最短路,就用
s
u
m
[
i
]
sum[i]
sum[i]加上
s
u
m
[
u
]
sum[u]
sum[u](
u
u
u表示从那个点到达点
i
i
i)。因为可能会有多条道路到达点
u
u
u,那么也就有多条道路到达点
i
i
i。
如果找到一条比原来最短路还要短的路,那么就更新一下
s
u
m
[
i
]
sum[i]
sum[i]和
d
i
s
[
i
]
dis[i]
dis[i]就行了。
初始化
s
u
m
[
1
]
=
1
sum[1]=1
sum[1]=1。其它搞一个SPFA就可以。
代码:
#include <cstdio>
#include <queue>
#define N 2000100
#define Inf 1e9
#define MOD 100003
using namespace std;
int n,m,x,y,k,head[N],dis[N],vis[N],sum[N];
struct edge
{
int next,to,dis;
}e[N];
void add(int from,int to) //邻接表存图
{
k++;
e[k].to=to;
e[k].dis=1;
e[k].next=head[from];
head[from]=k;
}
void spfa() //十分模板(不过话说SPFA我也没有见过什么变形,Floyd倒是一大堆)
{
for (int i=1;i<=n;i++)
{
dis[i]=Inf;
vis[i]=0;
}
queue<int> q;
q.push(1);
vis[1]=1;
dis[1]=0;
while (q.size())
{
int u=q.front();
q.pop();
vis[u]=0;
for (int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if (dis[v]>dis[u]+e[i].dis)
{
dis[v]=dis[u]+e[i].dis;
sum[v]=sum[u];
if (!vis[v])
{
q.push(v);
vis[v]=1;
}
}
else
if (dis[v]==dis[u]+e[i].dis) //又找到一条最短路
sum[v]=(sum[v]+sum[u])%MOD; //更新
}
}
}
int main()
{
scanf("%d%d",&n,&m);
while (m--)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
sum[1]=1;
spfa();
for (int i=1;i<=n;i++)
printf("%d\n",sum[i]%MOD);
return 0;
}