洛谷# T433456 DFS Timestamp
T433456 DFS Timestamp
题目描述
DFS Timestamp(时间戳),指的是在DFS的遍历过程中按照访问顺序给节点编号,时间戳有很多应用,一个重要的应用是在图连通性相关Tarjan算法中。
给定一个有向图(允许有重边和自环),输出各个节点的时间戳。
注意:
- DFS的过程中总是尽可能的从编号小的节点开始遍历,即从编号最小的节点开始遍历,
- 同时在遍历每个节点的出边时总是选择编号更小的节点开始遍历。
输入格式
第一行输入两个整数 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;
}

浙公网安备 33010602011771号