General idea of the topic
Someone put f l o y d floyd floyd is written as follows. How many more digraphs are there d i s [ u ] [ v ] dis[u][v] Is dis[u][v] correct?
point n ( n ≤ 2000 ) n(n\le 2000) n(n ≤ 2000), number of sides m ( m ≤ 5000 ) m(m\le 5000) m(m ≤ 5000), edge weight w ( 1 ≤ w ≤ 1 0 4 ) w(1\le w\le 10^4) w(1≤w≤104)
for i from 1 to n for j from 1 to n for k from 1 to n dis[i][j] <- min(dis[i][j], dis[i][k] + dis[k][j])
Solution
Test site: f l o y d floyd floyd implementation process
We can O ( n m log m ) O(nm\log m) O(nmlogm) n n n times d i j k s t r a dijkstra dijkstra algorithm is solved correctly d i s [ u ] [ v ] dis[u][v] dis[u][v].
Then we need to know what updates will make d i s [ u ] [ v ] dis[u][v] dis[u][v] it's also right to follow the wrong approach.
- When there is an edge ( u , v , w ) (u,v,w) (u,v,w), yes d i s [ u ] [ v ] = w dis[u][v] = w When dis[u][v]=w.
- When there are three points ( i , j , k ) (i,j,k) (i,j,k), yes d i s [ i ] [ k ] dis[i][k] dis[i][k] correct, d i s [ k ] [ j ] dis[k][j] dis[k][j] is correct, and k k k at this point i → j i\to j i → j on the shortest path.
We use arrays f 1 [ i ] [ j ] f1[i][j] f1[i][j] indicates d i s [ i ] [ j ] dis[i][j] dis[i][j] is correct. We use array f 2 [ i ] [ j ] f2[i][j] f2[i][j] indicates d i s [ j ] [ i ] dis[j][i] dis[j][i] is correct.
We use g [ i ] [ j ] g[i][j] g[i][j] save from i → j i\to j i → j is a set of points on all shortest paths.
As long as we enumerate each j j j. Then enumerate k k k. Let f 1 [ i ] [ k ] , f 2 [ k ] [ j ] f1[i][k],f2[k][j] f1[i][k],f2[k][j] are all true, and k ∈ g [ i ] [ j ] k\in g[i][j] k ∈ g[i][j], but it is obvious that the complexity is O ( n 3 ) O(n^3) O(n3), we need to consider using b i t s e t bitset bitset acceleration.
So when we implement it, we find the correct solution d i s [ u ] [ v ] dis[u][v] After dis[u][v], first traverse each edge and 1 1 1 judge and update f 1 , f 2 f1,f2 f1,f2 array.
Next, let's follow the wrong practice given by him i i i. Then put d i s [ i ] dis[i] After the dis[i] array is sorted in ascending order, it will be updated later according to the nearest node. If d i s [ i ] [ v ] = d i s [ i ] [ u ] + w dis[i][v] = dis[i][u] + w dis[i][v]=dis[i][u]+w description g [ i ] [ u ] g[i][u] All points in g[i][u] should be added to g [ i ] [ v ] g[i][v] In g[i][v], it is found here that we do not need two-dimensional g [ i ] [ j ] g[i][j] g[i][j] you can empty it every time you use it, and then you can add it to the collection b i t s e t bitset bitset operation.
Here's the last enumeration j j j. If f 1 [ i ] & f 2 [ j ] & g [ j ] f1[i]\&f2[j]\&g[j] F1 [i] &f2 [J] &g [J] any bit is 1 1 1 indicates that there is a point d i s [ i ] [ j ] dis[i][j] dis[i][j] is correct. Let's update it f 1 , f 2 f1,f2 f1,f2 array.
Finally f 1 f1 All in f1 1 1 1 together, there are points of infinity. The answer is to sum them together.
const int N = 2e3 + 7; ll n, m; vector<pai> G[N]; bitset<N> f1[N], f2[N], g[N]; int dis[N][N]; priority_queue<pai, vector<pai>, greater<pai>> pq; bool vis[N]; void dijkstra(int s, int* d) { fill(d + 1, d + 1 + n, INF); fill(vis + 1, vis + 1 + n, 0); d[s] = 0; pq.push({ 0,s }); while (pq.size()) { int u = pq.top().second; pq.pop(); if (vis[u]) continue; vis[u] = 1; for (auto& [v, w] : G[u]) { if (d[v] > d[u] + w) { d[v] = d[u] + w; pq.push({ d[v],v }); } } } } int tmp[N], ID; bool cmp(int x, int y) { return dis[ID][x] < dis[ID][y]; } int solve() { n = read(), m = read(); for (int i = 1; i <= m; ++i) { int u = read(), v = read(), w = read(); G[u].push_back({ v,w }); } for (int i = 1; i <= n; ++i) { dijkstra(i, dis[i]); f1[i].set(i); f2[i].set(i); } for (int u = 1; u <= n; ++u) { for (auto& [v, w] : G[u]) { if (dis[u][v] == w) { f1[u].set(v); f2[v].set(u); } } } for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { tmp[j] = j; g[j].reset(); g[j].set(j); } ID = i; sort(tmp + 1, tmp + 1 + n, cmp); for (int j = 1; j <= n; ++j) { int u = tmp[j]; for (auto& [v, w] : G[u]) { if (dis[i][v] == dis[i][u] + w) { g[v] |= g[u]; } } } for (int j = 1; j <= n; ++j) { if ((f1[i] & f2[j] & g[j]).any()) { f1[i].set(j); f2[j].set(i); } } } int res = 0; for (int i = 1; i <= n; ++i) res += f1[i].count(); for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { res += dis[i][j] == INF; } } print(res); return 1; }