题目描述
给出一个N个顶点M条边的无向无权图,顶点编号为1−N。问从顶点1开始,到其他每个点的最短路有几条。
输入格式
第一行包含2个正整数N,M,为图的顶点数与边数。
接下来M行,每行2个正整数x,y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边
输出格式
共N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出ans mod 100003后的结果即可。如果无法到达顶点i则输出0
用到的知识点
1、广度优先搜索
2、vector容器
开成一个vector数组,其实也可以用邻接表即链表的形式来储存数据
3、存储顶点深度的数组
dep[maxm]
4、存储顶点是否访问过的数组
vis[maxm]
5、储存最短路径条数的数组
cnt[maxn]:值得品味
6、循环条件为队列不为0
7、思考
可以使用一个类来表示顶点,类中的数据成员为顶点标识、顶点深度、是否被访问过;
再使用一个链表数组来代替vector类,具体操作方式与vector类相似;
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<queue>
using namespace std;
//广度优先搜素默认就是最短路径搜索
const int maxn = 1000000 + 1, maxm = 2000000 + 1, INF = 0x7f7f7f7f, MOD = 100003;
vector<int>G[maxn]; //这是一个vector数组
int dep[maxn];
bool vis[maxn]; //其中的数据都置为0
int cnt[maxn];
int main() {
int N, M; scanf("%d%d", &N, &M);
for (int i = 1; i <= M; i++) {
int x, y; scanf("%d%d", &x, &y);
G[x].push_back(y); //第x个顶点与第y个顶点相连(在这里面可以存放多个顶点)
G[y].push_back(x); //第y个顶点与第x个顶点相连
}
queue<int>Q; //创建队列
dep[1] = 0;
vis[1] = 1;
Q.push(1);
cnt[1] = 1;
while (!Q.empty()) { //判断队列是否为空
int x = Q.front(); //取出队列中最前面的元素
Q.pop(); //删除最前面的元素
for (int i = 0; i < G[x].size(); i++) {
int t = G[x][i]; //取出其中的一个顶点
if (!vis[t]) { //对于访问过的顶点不再操作
vis[t] = 1;
dep[t] = dep[x] + 1; //取出顶点的深度等于原来顶点深度+1
Q.push(t); //将该顶点挤入队列中等待被读取
}
if (dep[t] == dep[x] + 1) {
cnt[t] = (cnt[t] + cnt[x]) % MOD; //这里要算的是条数(cnt【i】保存的是到i顶点的最短路径数)
}
}
}
for (int i = 1; i <= N; i++) {
printf("%d\n", cnt[i]);
}
return 0;
}