洛谷# 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];
        }
    }
}
`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;
}
posted @ 2025-06-10 00:20  sirro1uta  阅读(36)  评论(0)    收藏  举报