洛谷# T433456 DFS Timestamp

T433456 DFS Timestamp

题目描述

DFS Timestamp(时间戳),指的是在DFS的遍历过程中按照访问顺序给节点编号,时间戳有很多应用,一个重要的应用是在图连通性相关Tarjan算法中。

给定一个有向图(允许有重边和自环),输出各个节点的时间戳。
注意:

  1. DFS的过程中总是尽可能的从编号小的节点开始遍历,即从编号最小的节点开始遍历,
  2. 同时在遍历每个节点的出边时总是选择编号更小的节点开始遍历。

输入格式

第一行输入两个整数 N M,其中 N 代表节点个数(从 1 开始编号),M 代表边的个数。接下来 M 行,每行为两个整数 u v 分别表示一条边的起点和终点。其中 1 <= u, v <= N。

输出格式

输出 N 行,第 i 行输出编号为 i 的节点的DFS Timestamp

输入输出样例 #1

输入 #1

3 1
1 2

输出 #1

1
2
3

输入输出样例 #2

输入 #2

4 3
1 4
2 3
1 2

输出 #2

1
2
3
4

说明/提示

数据规模和范围

对于100%的数据,1 <= N <= 10,000,0 <= M <= 100,000。

解:
本题主要是求对应点的访问顺序
主要是邻接图的读入、排序、遍历、输出四个部分组成

点击查看代码
int timestamp[MAXN]; //表示第几个被访问到的
int adj[MAXN][MAXN]; //边的连接关系
    // 读入图
    //把 v 加入到 u 的邻接点列表的末尾,然后更新出边计数
    for (int i = 0; i < m; i++) {
        int u, v;
        scanf("%d %d", &u, &v);
        adj[u][edgeCount[u]++] = v; //把 v 作为 u 的一个邻接点添加进去
    }

dfs经典递归

点击查看代码
void dfs(int u){ //从u开始
    visited[u] = 1;
    timestamp[u] = now++;
    for(int i = 0; i < edgeCount[u]; i++){
        int v = adj[u][i];
        if (!visited[v]) {
            dfs(v);
        }
    }
}

完整代码如下

点击查看代码
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>

#define MAXN 10005

int edgeCount[MAXN]; //边数
int timestamp[MAXN]; //表示第几个被访问到的
int adj[MAXN][MAXN]; //边的连接关系
int now = 1;
int visited[MAXN];
//邻接表的排序 升序
int cmp(const void* a, const void* b) {
    return (*(int*)a - *(int*)b);
}

void dfs(int u){ //从u开始
    visited[u] = 1;
    timestamp[u] = now++;
    for(int i = 0; i < edgeCount[u]; i++){
        int v = adj[u][i];
        if (!visited[v]) {
            dfs(v);
        }
    }
}

int main(){
    int n,m;
    scanf("%d%d",&n, &m);

    // 初始化
    memset(edgeCount, 0, sizeof(edgeCount));
    memset(visited, 0, sizeof(visited));
    // 读入图
    //把 v 加入到 u 的邻接点列表的末尾,然后更新出边计数
    for (int i = 0; i < m; i++) {
        int u, v;
        scanf("%d %d", &u, &v);
        adj[u][edgeCount[u]++] = v; //把 v 作为 u 的一个邻接点添加进去
    }
    // 对每个节点的邻接表排序
    for (int i = 1; i <= n; i++) {
        if (edgeCount[i] > 1) { //判断是否有多于一个出边
            qsort(adj[i], edgeCount[i], sizeof(int), cmp);
        }
    }
    // 从编号最小的节点开始 DFS(处理非连通图)
    for (int i = 1; i <= n; i++) {
        if (!visited[i]) {
            dfs(i);
        }
    }
    // 输出时间戳
    for (int i = 1; i <= n; i++) {
        printf("%d\n", timestamp[i]);
    }
    return 0;
}
posted @ 2025-05-23 00:27  sirro1uta  阅读(17)  评论(0)    收藏  举报