题目大意:
个点
条遍的无向图,如果点
在点
到点
的最短路径(
到
的边数最少)上,那么记这些点为集合
有
个询问,问集合
解题思路:
每次询问以u为起点跑一遍
,将以
为起点到其他点的最短路记为
,再以
为起点跑一遍
,记为
,若
那么
#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
const int inf = 1e9;
struct Line {
int to, w, next;
}e[5005];
priority_queue < pair<int, int> > q;
int n, m, u, v, cnt;
int dis[50][2], vis[50], last[50], a[5005];
inline void addline(int x, int y) {
e[++cnt] = (Line){y, 1, last[x]}; last[x] = cnt;
}
void dij(int S, int nm) {
for (int i = 1; i <= n; ++i) dis[i][nm] = inf, vis[i] = 0;
dis[S][nm] = 0;
while (q.size()) q.pop();
q.push(make_pair(0, S));
while (q.size()) {
int x = q.top().second; q.pop();
if (vis[x]) continue;
vis[x] = 1;
for (int i = last[x]; i; i = e[i].next) {
int y = e[i].to;
if (dis[y][nm] > dis[x][nm] + e[i].w) {
dis[y][nm] = dis[x][nm] + e[i].w;
if (!vis[y]) q.push(make_pair(-dis[y][nm], y));
}
}
}
return;
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 1, x = 0, y = 0; i <= m; ++i)
scanf("%d %d", &x, &y), addline(x, y), addline(y, x);
int Q = 0; scanf("%d", &Q);
while (Q--) {
scanf("%d %d", &u, &v);
dij(u, 0); dij(v, 1);
for (int i = 1; i <= n; ++i)
if (dis[i][0] + dis[i][1] == dis[v][0]) printf("%d ", i);
printf("\n");
}
}