2368. 受限条件下可到达节点的数目


BFS:
c
int reachableNodes(int n, int **edges, int edgesSize, int *edgesColSize, int *restricted, int restrictedSize)
{
// 创建并初始化受限节点标记数组
bool *isRestricted = (bool *)malloc(n * sizeof(bool));
for (int i = 0; i < n; i++) {
isRestricted[i] = false;
}
for (int i = 0; i < restrictedSize; i++) {
isRestricted[restricted[i]] = true;
}
// 如果节点0受限,直接返回0
if (isRestricted[0]) {
free(isRestricted);
return 0;
}
// 计算每个节点的度数,无向所以不区分入度与出度
int *degree = (int *)malloc(n * sizeof(int));
for (int i = 0; i < n; i++) {
degree[i] = 0;
}
for (int i = 0; i < edgesSize; i++) {
int u = edges[i][0];
int v = edges[i][1];
degree[u]++;
degree[v]++;
}
// 创建邻接表
int **graph = (int **)malloc(n * sizeof(int*));
int *graphSize = (int *)malloc(n * sizeof(int));
for (int i = 0; i < n; i++) { // 因为题目中 2 <= n <= 10^5, 所以需动态申请
graph[i] = (int *)malloc(degree[i] * sizeof(int));
graphSize[i] = 0; // 初始化当前邻居数量
}
// 填充邻接表
for (int i = 0; i < edgesSize; i++) {
int u = edges[i][0];
int v = edges[i][1];
graph[u][graphSize[u]++] = v;
graph[v][graphSize[v]++] = u;
}
// 创建并初始化访问标记数组
bool *visited = (bool *)malloc(n * sizeof(bool));
for (int i = 0; i < n; i++) visited[i] = false;
visited[0] = true;
int *queue = (int*)malloc(n * sizeof(int));
int head = 0, tail = 0;
queue[tail++] = 0; // 从节点0开始
int count = 1; // 包括节点0
// BFS遍历
while (head < tail) {
int u = queue[head++];
for (int i = 0; i < graphSize[u]; i++) {
int v = graph[u][i];
if (!visited[v] && !isRestricted[v]) {
visited[v] = true;
count++;
queue[tail++] = v;
}
}
}
// 释放内存
free(isRestricted);
free(degree);
for (int i = 0; i < n; i++) {
free(graph[i]);
}
free(graph);
free(graphSize);
free(visited);
free(queue);
return count;
}
DFS:
c
void dfs(int u, int **graph, int *graphSize, bool *visited, bool *isRestricted, int *count)
{
for (int i = 0; i < graphSize[u]; i++) {
int v = graph[u][i];
if (!visited[v] && !isRestricted[v]) {
visited[v] = true;
(*count)++;
dfs(v, graph, graphSize, visited, isRestricted, count);
}
}
}
int reachableNodes(int n, int **edges, int edgesSize, int *edgesColSize, int *restricted, int restrictedSize)
{
// 创建并初始化受限节点标记数组
bool *isRestricted = (bool *)malloc(n * sizeof(bool));
for (int i = 0; i < n; i++) isRestricted[i] = false;
for (int i = 0; i < restrictedSize; i++) {
isRestricted[restricted[i]] = true;
}
// 如果节点0受限,直接返回0
if (isRestricted[0]) {
free(isRestricted);
return 0;
}
// 计算每个节点的度数
int *degree = (int *)malloc(n * sizeof(int));
for (int i = 0; i < n; i++) degree[i] = 0;
for (int i = 0; i < edgesSize; i++) {
int u = edges[i][0];
int v = edges[i][1];
degree[u]++;
degree[v]++;
}
// 创建邻接表
int **graph = (int **)malloc(n * sizeof(int *));
int *graphSize = (int *)malloc(n * sizeof(int));
for (int i = 0; i < n; i++) {
graph[i] = (int *)malloc(degree[i] * sizeof(int));
graphSize[i] = 0; // 初始化当前邻居数量
}
// 填充邻接表
for (int i = 0; i < edgesSize; i++) {
int u = edges[i][0];
int v = edges[i][1];
graph[u][graphSize[u]++] = v;
graph[v][graphSize[v]++] = u;
}
// 创建并初始化访问标记数组
bool *visited = (bool *)malloc(n * sizeof(bool));
for (int i = 0; i < n; i++) visited[i] = false;
visited[0] = true;
int count = 1; // 从节点0开始计数
dfs(0, graph, graphSize, visited, isRestricted, &count);
// 释放内存
free(isRestricted);
free(degree);
for (int i = 0; i < n; i++) {
free(graph[i]);
}
free(graph);
free(graphSize);
free(visited);
return count;
}
1466. 重新规划路线


c
typedef struct {
int to; // 邻接节点
int weight; // 权值:1表示需要反转,0表示不需要
} Edge;
int minReorder(int n, int **connections, int connectionsSize, int *connectionsColSize)
{
// 1. 统计每个节点的度数(邻接点数量)
int *degree = (int*)malloc(n * sizeof(int));
memset(degree, 0, n * sizeof(int));
for (int i = 0; i < connectionsSize; i++) {
int u = connections[i][0];
int v = connections[i][1];
degree[u]++;
degree[v]++;
}
// 2. 为邻接表分配空间
Edge **graph = (Edge **)malloc(n * sizeof(Edge*));
for (int i = 0; i < n; i++) {
graph[i] = (Edge *)malloc(degree[i] * sizeof(Edge));
}
int *index = (int *)malloc(n * sizeof(int));
memset(index, 0, n * sizeof(int));
// 3. 构建邻接表(添加正向和反向边)
for (int i = 0; i < connectionsSize; i++) {
int u = connections[i][0];
int v = connections[i][1];
// 添加正向边:u->v,权值1(需要反转)
graph[u][index[u]++] = (Edge){v, 1};
// 添加反向边:v->u,权值0(不需要反转)
graph[v][index[v]++] = (Edge){u, 0};
}
// 4. 使用数组实现BFS队列
int *queue = (int*)malloc(n * sizeof(int)); // BFS队列
int head = 0, tail = 0; // 队列头尾指针
int *visited = (int*)malloc(n * sizeof(int));
memset(visited, 0, n * sizeof(int));
int res = 0; // 需要反转的边数
queue[tail++] = 0;
visited[0] = 1;
// 5. BFS
while (head < tail) {
int u = queue[head++]; // 出队
for (int i = 0; i < degree[u]; i++) {
int v = graph[u][i].to;
int weight = graph[u][i].weight;
if (visited[v] == 0) {
if (weight == 1) {
res++; // 需要反转的边
}
visited[v] = 1;
queue[tail++] = v; // 入队
}
}
}
// 6. 释放资源
free(degree);
free(index);
free(visited);
free(queue);
for (int i = 0; i < n; i++) {
free(graph[i]);
}
free(graph);
return res;
}