2021 Niuke summer multi school training camp 7 xay loves Floyd

Keywords: Graph Theory

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.

  1. 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.
  2. 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;
}

Posted by srinivas6203 on Sun, 31 Oct 2021 22:55:40 -0700