P3906 Geodetic集合 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
把无向边看作长度均为1的有向边然后求最短路即可。但是此题需要把所有最短路上的点放入集合。并随机取两点访问,首先会想到floyd,处理完最短路后枚举顶点。
设起始点终点为 s ,e 和 k如果满足:
则说明k节点在s<->e的最短路上。
同理,我们也可以使用dijkstra ,但是dij是单元最短路,此图为无向边,所以需要起点跑一遍最短路,终点跑一遍最短路。然后同样用上面的条件判断即可得到节点是否在最短路上。
Floyd O(n^3)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define int ll
#define mm(a) memset(a,0,sizeof(a))
#pragma warning(disable:4996);
const int N = 2e3 + 10;
const int mod = 998244353;
int T, n, m, k, q, t,x;
int arr[N];
vector<int>gra[N];
int g[N][N];
void floyd() {
for (int k = 1; k <= n; k++) {
for (int j = 1; j <= n; j++) {
for (int i = 1; i <= n; i++) {
g[j][i] = g[i][j] = min(g[j][i], g[j][k] + g[k][i]);
}
}
}
}
signed main() {
cin >> n >> m;
for (int j = 1; j <= n; j++) {//初始化,记得判断i==j
for (int i = 1; i <= n; i++) {
if (i == j)continue;
g[i][j] = g[j][i] = INT_MAX;
}
}
int a, b;
for (int j = 1; j <= m; j++) {
cin >> a >> b;
g[a][b] = 1;
g[b][a] = 1;
}
floyd();
cin >> k;
while (k--) {
cin >> a >> b;
for(int j=1;j<=n;j++)
if (g[a][j] + g[j][b] == g[a][b]) {
cout << j << " ";
}
cout << endl;
}
}
Dijkstra(n^2log)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define int ll
#define mm(a) memset(a,0,sizeof(a))
#pragma warning(disable:4996);
const int N = 2e3 + 10;
const int mod = 998244353;
int T, n, m, k, q, t,x;
int arr[N];
struct node {
int to, pw;
int operator<(const node& a)const {
return pw > a.pw;
}
};
vector<node>gra[N];
int dis1[N], dis2[N];
void dij1(int s) {
for (int j = 1; j <= n; j++)dis1[j] = INT_MAX;
int vis[N] = { 0 };
int now = s;
dis1[now] = 0;
priority_queue<node>q;
q.push({ now,dis1[now] });
while (!q.empty()) {
now = q.top().to;
q.pop();
if (vis[now])continue;
vis[now] = 1;
for ( auto& x : gra[now]) {
int to = x.to;
if (!vis[to] && dis1[to] > dis1[now] + x.pw) {
dis1[to] = dis1[now] + x.pw;
q.push({ to,dis1[to] });
}
}
}
}
void dij2(int s) {
for (int j = 1; j <= n; j++)dis2[j] = INT_MAX;
int vis[N] = { 0 };
int now = s;
dis2[now] = 0;
priority_queue<node>q;
q.push({ now,dis2[now] });
while (!q.empty()) {
now = q.top().to;
q.pop();
if (vis[now])continue;
vis[now] = 1;
for (auto& x : gra[now]) {
int to = x.to;
if (!vis[to] && dis2[to] > dis2[now] + x.pw) {
dis2[to] = dis2[now] + x.pw;
q.push({ to,dis2[to] });
}
}
}
}
signed main() {
ios::sync_with_stdio(0); cin.tie(0);
#ifndef ONLINE_JUDGE
freopen("out.txt", "w", stdout);
#endif // !ONLINE_JUDGE
cin >> n >> m;
int a, b;
for (int j = 1; j <= m; j++) {
cin >> a >> b;
gra[a].push_back({b,1});
gra[b].push_back({a,1});
}
cin >> k;
while (k--) {
cin >> a >> b;
dij1(a);
dij2(b);
for (int j = 1; j <= n; j++) {
if (dis1[j] + dis2[j] == dis1[b]) {
cout << j << " ";
}
//cout << dis1[j] << " ";
}
cout << endl;
}
}