最短路计数,次短路计数
https://www.acwing.com/problem/content/385/
acwing 1134.最短路计数

①$bfs$ 每个点只出队一次,且入队一次
②$dijkstra$ 每个点第一次出队的序列一定满足拓扑序
③$bellman-ford(spfa)$ 出队的时候都不一定是满足最小,每个点可能出队多次,有可能更新前面已经出队的点,不具备拓扑序
但是要用$spfa$求最短路径数,也是可以的。比如当边权有负数时,就只能用$spfa$,先用$spfa$跑一遍,将每个点的最短路径跑出,然后建立最短路径树,在树上进行$dp$(拓扑排序)。
当$dis[j] > dis[t] + 1$时,转移,并将$cnt[t]$的值赋给$cnt[j]$, 当$dis[j] = dis[t] + 1$时,累加,将$cnt[j] = (cnt[j] + cnt[t])$。
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <queue> 5 6 using namespace std; 7 8 const int mod = 100003; 9 10 const int N = 1e5 + 10, M = 4e5 + 10; 11 int e[M], ne[M], h[N], idx; 12 int dis[N]; 13 bool st[N]; 14 int cnt[N]; 15 int n, m; 16 17 void add(int a, int b) 18 { 19 e[idx] = b, ne[idx] = h[a], h[a] = idx ++; 20 } 21 22 void bfs() 23 { 24 memset(dis, 0x3f, sizeof dis); 25 dis[1] = 0; 26 cnt[1] = 1; 27 queue<int> q; 28 q.push(1); 29 30 while(q.size()) 31 { 32 int t = q.front(); 33 q.pop(); 34 35 for(int i = h[t] ; ~ i ; i = ne[i]) 36 { 37 int j = e[i]; 38 if(dis[j] > dis[t] + 1) 39 { 40 dis[j] = dis[t] + 1; 41 cnt[j] = cnt[t]; 42 q.push(j); 43 } 44 else if(dis[j] == dis[t] + 1) 45 { 46 cnt[j] = (cnt[j] + cnt[t]) % mod; 47 } 48 } 49 } 50 } 51 52 int main(){ 53 cin >> n >> m; 54 55 memset(h, -1, sizeof h); 56 while(m --) 57 { 58 int a, b; 59 cin >> a >> b; 60 add(a, b), add(b, a); 61 } 62 63 bfs(); 64 65 for(int i = 1 ; i <= n ; i ++)cout << cnt[i] << endl; 66 return 0; 67 }
https://www.acwing.com/activity/content/problem/content/1506/1/
acwing 383.观光


在求最短路数的基础上进行求次短路数。和在树中求最大直径和次大直径的方法一样。在最短路数的基础上:
①如果当前小于最短路,先更新次短路数,加入堆,再更新最短路数,加入堆;
②再如果当前等于最短路,累加最短路数;
③再如果当前小于次短路,更新次短路数,加入堆;
④最后如果当前等于次短路数,累加次短路数。
次短路数和最短路数一样,都是满足拓扑序的,所以使用$dijkstra$算法求解。
1 #include <iostream> 2 #include <algorithm> 3 #include <queue> 4 #include <cstring> 5 #include <vector> 6 7 using namespace std; 8 9 const int N = 1010, M = 20010; 10 11 struct Node{ 12 int ver, type, dis; 13 bool operator > (const Node &W)const{ 14 return dis > W.dis; 15 } 16 }; 17 18 int e[M], ne[M], w[M], h[N], idx; 19 int dis[N][2], cnt[N][2]; 20 bool st[N][2]; 21 int n, m; 22 int S, E; 23 24 void add(int a, int b, int c) 25 { 26 e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++; 27 } 28 29 int dijkstra() 30 { 31 memset(st, 0, sizeof st); 32 memset(dis, 0x3f, sizeof dis); 33 memset(cnt, 0, sizeof cnt);//多组测试数据必须全部初始化 34 priority_queue<Node, vector<Node>, greater<Node>> heap; 35 dis[S][0] = 0; 36 cnt[S][0] = 1;//最开始没有次短路 37 heap.push({S, 0, 0}); 38 39 while(heap.size()) 40 { 41 Node t = heap.top(); 42 heap.pop(); 43 44 int ver = t.ver, type = t.type, distance = t.dis, count = cnt[ver][type]; 45 if(st[ver][type])continue; 46 st[ver][type] = true; 47 48 for(int i = h[ver] ; ~ i ; i = ne[i]) 49 { 50 int j = e[i]; 51 if(dis[j][0] > distance + w[i])//分别对应一二三四种情况。 52 { 53 dis[j][1] = dis[j][0], cnt[j][1] = cnt[j][0]; 54 heap.push({j, 1, dis[j][1]}); 55 dis[j][0] = distance + w[i], cnt[j][0] = count; 56 heap.push({j, 0, dis[j][0]}); 57 } 58 else if(dis[j][0] == distance + w[i])cnt[j][0] += count; 59 else if(dis[j][1] > distance + w[i]) 60 { 61 dis[j][1] = distance + w[i], cnt[j][1] = count; 62 heap.push({j, 1, dis[j][1]}); 63 } 64 else if(dis[j][1] == distance + w[i])cnt[j][1] += count; 65 } 66 } 67 int res = cnt[E][0]; 68 if(dis[E][0] + 1 == dis[E][1])res += cnt[E][1]; 69 return res; 70 } 71 72 int main(){ 73 int T; 74 cin >> T; 75 while(T --) 76 { 77 cin >> n >> m; 78 memset(h, -1, sizeof h); 79 idx = 0;//注意多组数据,idx和表头都要初始化 80 while(m --) 81 { 82 int a, b, c; 83 cin >> a >> b >> c; 84 add(a, b, c); 85 } 86 87 cin >> S >> E; 88 89 cout << dijkstra() << endl; 90 } 91 return 0; 92 }

浙公网安备 33010602011771号