摘要:
最短路计数问题
问题描述:
题目连接洛谷P1144最短路计数
算法分析:
本题实际上是一道简单的最短路求解的模板题。在迪杰斯特拉算法或者spfa算法模板的基础上加上负责计数的数组count即可。
值得注意的是本题目是无向不加权图,因此也可以使用BFS求解。
代码以及详细注释:
#include <iostream>
#include <vector>
#include <queue>
#define INF 10000000
using namespace std;
#pragma warning(disable:4996)
struct edge {
int to;
int next;
int w;
};
struct Node {
int pos;
int w;
Node(int _to = 0, int _w = 0 ) :pos(_to), w(_w) {};
bool operator()(Node& n1, Node& n2) {
return n1.w > n2.w;
}
};
class Solution {
public:
int n, m;
//链式前向星建图
int cnt = 0;
vector<int> head;
vector<edge> e;
vector<int> dfs;
vector<int> count;
//堆优化
priority_queue<Node, vector<Node>, Node> q;
vector<bool> visit; //
inline void add_edge(int u, int v, int w) {
cnt++;
e[cnt].to = v;
e[cnt].w = w;
e[cnt].next = head[u];
head[u] = cnt;
}
void dijskral_count() {
cin >> n >> m;
head.resize(n + 1, 0);
count.resize(n + 1, 0);
dfs.resize(n + 1, INF);
visit.resize(n + 1, false);
e.resize(2*m + 1);
for (int i = 1; i <= m; ++i) {
int u, v;
cin >> u >> v;
add_edge(u, v,1); //无向图,插入两次 终点和起点相反
add_edge(v, u,1);
}
int s = 1;
dfs[s] = 0;
q.push(Node(s, 0));//记录起点到起点的最短距离为0,且只有一条
count[s] = 1;
while (!q.empty())
{
Node temp = q.top();
q.pop();
int pos = temp.pos;
if (visit[pos])
continue;
visit[pos] = true;
for (int i = head[pos]; i != 0; i = e[i].next)
{
int y = e[i].to;
if (dfs[y] > dfs[pos] + e[i].w)
{
count[y] = count[pos];
dfs[y] = dfs[pos] + e[i].w;
if(!visit[y])
q.push(Node(y, dfs[y]));
}
else if(dfs[y] == dfs[pos] + e[i].w)
count[y] = (count[y] + count[pos]) % 100003;
}
}
for (int i = 1; i <= n; ++i)
cout << count[i] << endl;
}
};
int main() {
//freopen("in.txt", "r", stdin);
Solution s;
s.dijskral_count();
return 0;
}