#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 2000010
#define INF 0x3f3f3f3f
// 邻接表节点结构体
typedef struct Edge {
int v;
struct Edge* next;
} Edge;
// 用于存储每个顶点的邻接表表头指针
Edge* adjList[N];
// 记录从起点到每个顶点的最短路径长度
int dist[N];
// 结构体用于在队列中存储顶点及其距离信息(模拟优先队列中的元素)
typedef struct Node {
int id;
int dis;
} Node;
// 队列结构体
typedef struct Queue {
Node* data;
int front;
int rear;
int size;
} Queue;
// 队列初始化函数
void initQueue(Queue* q) {
q->data = (Node*)malloc(sizeof(Node) * N);
q->front = q->rear = 0;
q->size = 0;
}
// 入队函数
void enqueue(Queue* q, Node node) {
q->data[q->rear] = node;
q->rear = (q->rear + 1) % N;
q->size++;
}
// 出队函数
Node dequeue(Queue* q) {
Node node = q->data[q->front];
q->front = (q->front + 1) % N;
q->size--;
return node;
}
// 判断队列是否为空
int isEmpty(Queue* q) {
return q->size == 0;
}
// Dijkstra算法实现函数
void dijkstra(int s, int n) {
memset(dist, INF, sizeof(dist));
dist[s] = 0;
Queue q;
initQueue(&q);
Node start = {s, 0};
enqueue(&q, start);
while (!isEmpty(&q)) {
Node now = dequeue(&q);
int u = now.id;
int d = now.dis;
if (d > dist[u]) continue;
Edge* p = adjList[u];
while (p != NULL) {
int v = p->v;
if (dist[v] > dist[u] + 1) {
dist[v] = dist[u] + 1;
Node newNode = {v, dist[v]};
enqueue(&q, newNode);
}
p = p->next;
}
}
}
// 释放邻接表内存函数(避免内存泄漏)
void freeAdjList() {
for (int i = 0; i < N; i++) {
Edge* p = adjList[i];
while (p != NULL) {
Edge* next = p->next;
free(p);
p = next;
}
}
}
int main() {
int n, m, s;
scanf("%d%d%d", &n, &m, &s);
// 初始化邻接表表头指针为NULL
memset(adjList, 0, sizeof(adjList));
// 读入边的信息,构建邻接表
for (int i = 0; i < m; i++) {
int u, v;
scanf("%d%d", &u, &v);
Edge* newEdge = (Edge*)malloc(sizeof(Edge));
newEdge->v = v;
newEdge->next = adjList[u];
adjList[u] = newEdge;
}
dijkstra(s, n);
// 输出从起点到各个顶点的最短路径长度,若不存在路径则输出 -1
for (int i = 1; i <= n; i++) {
if (dist[i] == INF)
printf("-1 ");
else
printf("%d ", dist[i]);
}
printf("\n");
freeAdjList();
return 0;
}