怎么求多源点到多目的地的最短距离
原理是,设计一个超级远点S,S和每个源点建立一条边权为0的路径。(这个S是假想的,实际实现的时候可不需建立)
另一个原理是,队列的两个性质:1. 两端性,2.单调性
队列里面只可能出现 [x,x,x ..., x+1, x+1, ...]
不会同时出现x, x+1, x+2
实现的时候只需要把所有源点push到队列里就行了。
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
char g[N][N];
int dist[N][N];
int n, m;
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
scanf("%s", g[i] + 1);
}
queue<pair<int, int>> q;
memset(dist, -1, sizeof dist);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (g[i][j] == '1') {
dist[i][j] = 0;
q.push({i, j});
}
}
}
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
while (q.size()) {
auto pos = q.front();
q.pop();
int x = pos.first, y = pos.second;
for (int i = 0; i < 4; i++) {
int a = x + dx[i], b = y + dy[i];
if (a >= 1 && a <= n && b >= 1 && b <= m && dist[a][b] == -1) {
dist[a][b] = dist[x][y] + 1;
q.push({a, b});
}
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cout << dist[i][j]<<" ";
}
cout << endl;
}
}
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
bool g[N][N];
int dist[N][N];
int n, m, k, d;
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
struct Tar {
int x, y, c;
} trg[N * N];
queue<pair<int, int>> q;
void bfs() {
while (q.size()) {
auto u = q.front();
q.pop();
int x = u.first, y = u.second;
for (int i = 0; i < 4; i++) {
int a = x + dx[i], b = y + dy[i];
if (a >= 1 && a <= n && b >= 1 && b <= n && !g[a][b]) {
if (dist[a][b] > dist[x][y] + 1) {
dist[a][b] = dist[x][y] + 1;
q.push({a, b});
}
}
}
}
}
int main() {
ios::sync_with_stdio(false);
cin >> n >> m >> k >> d;
memset(dist, 0x3f, sizeof dist);
while (m--) {
int x, y;
cin >> x >> y;
q.push({x, y});
dist[x][y] = 0;
}
for (int i = 0; i < k; i++) {
int x, y, c;
cin >> x >> y >> c;
trg[i] = {x, y, c};
}
while (d--) {
int x, y;
cin >> x >> y;
g[x][y] = true;
}
bfs();
long long res = 0;
for (int i = 0; i < k; i++) {
int cost = 1ll * dist[trg[i].x][trg[i].y] * trg[i].c;
res += cost;
}
cout << res << endl;
}