洛谷 P1144 最短路计数 无向无权图(bfs或者优化dijkstra)
题意:
题目的意思是给出一个无向无权图,图中结点的编号为1~n,把编号为1的结点定义为初始结点,求这个初始结点到其他每个点的最短路径有多少条。
注意:可能包含自环或者重边。
题解:
首先这是一张无向无权图,所以可以很自然地想到bfs,当然,用优化的dijkstra也是可以的。
其实这道题自环对结果没有影响的,因为一个点到自己的最短路只有一条;然后考虑重边,我们只要把重边重复计算即可。
代码如下:
方法一:优化的dijkstra
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<cmath>
#include<queue>
#include<cstring>
#include<vector>
#include<map>
#define MAX 1000005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int n,m,mod=1e5+3;//n为顶点数,m为边的数量,s为开始点
int visit[MAX],dis[MAX],ans[MAX];//ans[]记录到每个点的最短路径有多少条
map<int,int> mp;
struct edge{//存储边
int to;//边的指向
int cost;//边的权值
};
vector<edge> adj[MAX];
typedef pair<int,int> p; //first是最短距离,second是顶点的编号
struct cmp{//优先队列的cmp是一个类
bool operator()(p a,p b) {
return a.first>b.first;
}
};
void dijkstra(int s){
for(int i=0;i<MAX;i++){
visit[i]=0;
dis[i]=INF;
}
dis[s]=0,ans[s]=1;
priority_queue<p,vector<p>,cmp > q;
q.push(p(0,s));//将源结点放入优先队列
while(!q.empty()){
p top=q.top();
q.pop();
int u=top.second;
if(visit[u]==0){
visit[u]=1;
for(int i=0;i<adj[u].size();i++){
edge e=adj[u][i];
if(dis[e.to]>dis[u]+e.cost){
dis[e.to]=dis[u]+e.cost;
ans[e.to]=ans[u];
q.push(p(dis[e.to],e.to));
}else if(dis[e.to]==dis[u]+e.cost){
ans[e.to]+=ans[u];
ans[e.to]%=mod;
}
}
}
}
}
int main(){
cin>>n>>m;
int a,b;
for(int i=0;i<m;i++){
cin>>a>>b;
edge e;
e.to=b;
e.cost=1;//权值为1
adj[a].push_back(e);//adj[a]是从顶点a出发的边的集合
e.to=a;
adj[b].push_back(e);
}
dijkstra(1);
for(int i=1;i<=n;i++){
printf("%d\n",ans[i]);
}
return 0;
}
方法二:bfs
一个点最短路一定经过了一个层数比它少一的结点(否则不是最短路)。
所以用每个相邻且层数比当前结点层数少一的点更新当前点的路径跳数即可。
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<cmath>
#include<queue>
#include<cstring>
#include<vector>
#include<map>
#define MAX 1000005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int n,m,mod=1e5+3;
int ans[MAX],dep[MAX],visit[MAX];
vector<int> adj[MAX];//邻接表
void bfs(int s){//源点为s
ans[s]=1,visit[s]=1,dep[1]=0;
queue<int> q;
q.push(s);
while(!q.empty()){
int top=q.front();
q.pop();
for(int i=0;i<adj[top].size();i++){
int t=adj[top][i];
if(visit[t]==0){
dep[t]=dep[top]+1;
visit[t]=1;
q.push(t);
}
if(dep[t]==dep[top]+1){
ans[t]+=ans[top];
ans[t]%=mod;
}
}
}
}
int main(){
scanf("%d%d",&n,&m);
int a,b;
for(int i=0;i<m;i++){
scanf("%d%d",&a,&b);
adj[a].push_back(b);
adj[b].push_back(a);
}
bfs(1);//bfs
for(int i=1;i<=n;i++){//输出结果
printf("%d\n",ans[i]);
}
return 0;
}