洛谷P1144最短路計數題解
阿新 • • 發佈:2018-11-05
最短路計數
此題還是尋找從1到i點總共有幾個最短路且每條邊的邊長為1,對於這種尋找最短路的個數,我們可以反向搜尋,即先用\(SPFA\)預處理出所有點的最短路,然後我們反向記憶化搜尋,可以用\(sum[i]\)表示從i到1的最短路個數,然後我們初始化\(sum[1] = 1\),然後就可以了
程式碼:
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> #define rqy 100003 using namespace std; int n, m, lin[1000100], tot, dis[1000010], sum[1000010] = {0, 1}, vis[1000010]; queue <int> q; struct cym{ int to, next; }e[1000100]; void add(int u,int v) { e[++tot].to = v; e[tot].next = lin[u]; lin[u] = tot; } int dfs(int u)//反向搜尋 { if (sum[u]) return sum[u]; for (int i = lin[u]; i; i = e[i].next) if (dis[u] == dis[e[i].to] + 1) sum[u] = (sum[u] + dfs(e[i].to)) % rqy; return sum[u]; } int main() { scanf("%d%d", &n, &m); memset(dis, 0x3f, sizeof(dis)); dis[1] = 0; q.push(1); for (int i = 1; i <= m; i++) { int x, y; scanf("%d%d", &x, &y); add(x, y); add(y, x); } while (!q.empty()) { int cur = q.front(); q.pop(); vis[cur] = 0; for (int i = lin[cur]; i; i = e[i].next) { if (dis[cur] + 1 < dis[e[i].to]) { dis[e[i].to] = dis[cur] + 1; if (!vis[e[i].to]) { q.push(e[i].to); vis[e[i].to] = 1; } } } } for (int i = 1; i <= n; i++) printf("%d\n", dfs(i)); }