洛谷# P3916 图的遍历
P3916 图的遍历
题目描述
给出 $N$ 个点,$M$ 条边的有向图,对于每个点 $v$,令 $A(v)$ 表示从点 $v$ 出发,能到达的编号最大的点。现在请求出 $A(1),A(2),\dots,A(N)$ 的值。
输入格式
第 $1$ 行 $2$ 个整数 $N,M$,表示点数和边数。
接下来 $M$ 行,每行 $2$ 个整数 $U_i,V_i$,表示边 $(U_i,V_i)$。点用 $1,2,\dots,N$ 编号。
输出格式
一行 $N$ 个整数 $A(1),A(2),\dots,A(N)$。
输入输出样例 #1
输入 #1
4 3
1 2
2 4
4 3
输出 #1
4 4 3 4
说明/提示
- 对于 $60%$ 的数据,$1 \leq N,M \leq 10^3$。
- 对于 $100%$ 的数据,$1 \leq N,M \leq 10^5$。
题解
首先来构造邻接表
先定义这样的函数来加入边
用的是数组模拟邻接表的头插法,比较简便
点击查看代码
void add_edge(int u, int v){
edges[tot].to = v;
edges[tot].next = head[u];
head[u] = tot; //u出发的边链表现在从这条新边开始
tot++;
}
这道题要求我们找出每个点能到达点中编号最大的点
关键在dfs
点击查看代码
void dfs(int u){
visited[u] = 1;
for(int i = head[u]; i; i = edges[i].next){
int v = edges[i].to;
if(!visited[v]){
dfs(v);
}
if(A[v] > A[u]){
A[u] = A[v];
}
}
}
完整代码如下
点击查看代码
#include <stdio.h>
#define MAXN 100005
struct Edge{
int to,next;
};
struct Edge edges[MAXN];
int head[MAXN];
int tot = 1;
int visited[MAXN];
int A[MAXN];
void add_edge(int u, int v){
edges[tot].to = v;
edges[tot].next = head[u];
head[u] = tot; //u出发的边链表现在从这条新边开始
tot++;
}
void dfs(int u){
visited[u] = 1;
for(int i = head[u]; i; i = edges[i].next){
int v = edges[i].to;
if(!visited[v]){
dfs(v);
}
if(A[v] > A[u]){
A[u] = A[v];
}
}
}
int main(){
int n,m;
scanf("%d%d",&n, &m);
for(int i = 0; i < m; i++){
int u, v;
scanf("%d%d", &u, &v);
add_edge(u, v); //有向图
}
for(int i = 1; i <= n; i++){
A[i] = i;
}
for(int i = n; i >= 1; i--){
if (!visited[i]){
dfs(i);
}
}
for(int i = 1; i <= n; i++){
printf("%d ", A[i]);
}
printf("\n");
return 0;
}

浙公网安备 33010602011771号