传送门
题目大意
给出一个 N N N 个顶点 M M M 条边的无向无权图,顶点编号为 1 ∼ N 1\sim N 1∼N。问从顶点 1 1 1 开始,到其他每个点的最短路有几条。
思路
d
i
j
dij
dij求最短路
增加
a
n
s
ans
ans数组记录答案
如果刚计算出最短路,
a
n
s
[
v
]
=
a
n
s
[
u
]
ans[v]=ans[u]
ans[v]=ans[u]
如果最短路相同,
a
n
s
[
v
]
+
=
a
n
s
[
u
]
ans[v]+=ans[u]
ans[v]+=ans[u]
代码
int n,m,q=0;;
struct Edge{
int u;
int v;
int w;
int nxt;
}edge[maxn];
int head[maxn];
void add(int u,int v){//链式前向星
edge[++q].u=u;
edge[q].v=v;
edge[q].w=1;
edge[q].nxt=head[u];
head[u]=q;
}
struct node{
int x;
int cnt;
};
bool operator <(const node& a,const node& b){
return a.cnt > b.cnt;
} //这里以大于重载小于是因为默认情况下,优先队列是以大的作为队首,这样一反,就可以再默认情况下使得小的作为队首
int dis[maxn],ans[maxn];
int vis[maxn];
void dij(int x){
memset(dis,0x3f,sizeof dis);//最大
memset(ans,0,sizeof ans);
priority_queue<node> q;
dis[x]=0;
ans[x]=1;
q.push({x,0});
while(!q.empty()){
node tmp=q.top();
q.pop();
int u=tmp.x,d=tmp.cnt;
if(vis[u]) continue;
vis[u]=0;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].v;
if(dis[v]>dis[u]+edge[i].w){
dis[v]=dis[u]+edge[i].w;
ans[v]=ans[u];
q.push({v,dis[v]});
}
else if(dis[v]==dis[u]+edge[i].w){
ans[v]=(ans[u]+ans[v])%100003;
}
}
}
}
int main(){
scanf("%d%d",&n,&m);
int u,v;
for(int i=1;i<=m;i++){
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dij(1);
for(int i=1;i<=n;i++){
printf("%lld\n",ans[i]);
}
}