前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >P3916 图的遍历【反向建边 + DFS】

P3916 图的遍历【反向建边 + DFS】

作者头像
Lokinli
发布2023-03-09 13:36:09
4410
发布2023-03-09 13:36:09
举报
文章被收录于专栏:以终为始

https://www.luogu.com.cn/problem/P3916

题目描述

给出NN个点,MM条边的有向图,对于每个点vv,求A(v)A(v)表示从点vv出发,能到达的编号最大的点。

输入格式

第1 行,2 个整数N,MN,M。

接下来MM行,每行2个整数U_i,V_iUi​,Vi​,表示边(U_i,V_i)(Ui​,Vi​)。点用1, 2,\cdots,N1,2,⋯,N编号。

输出格式

N 个整数A(1),A(2),\cdots,A(N)A(1),A(2),⋯,A(N)。

输入输出样例

输入 #1复制

代码语言:javascript
复制
4 3
1 2
2 4
4 3

输出 #1复制

代码语言:javascript
复制
4 4 3 4

说明/提示

• 对于60% 的数据,1 \le N . M \le 10^31≤N.M≤103;

• 对于100% 的数据,1 \le N , M \le 10^51≤N,M≤105。

题解:反向建边,再进行搜索。例如题目中,反向建边后是:2->1,4->2,3->4,从大到小开始DFS。(反向建边后,如果遍历该节点连接的边,即能够到达的地方,比如e[4] 里面存储了2,那么2一定能到达4,如果之后遍历3,2,1的时候,一定也不会比4大。关键是从大到小进行了遍历。)这样子如果当前点的ans[ ]有数值了,就说明已经遍历过了,而且肯定比当前要大,就不需要再继续遍历下去。

碎碎念:正常建边,然后跑DFS,一大半样例会TLE,只有我这样子的憨憨才会这样子做。。。

代码思路源于洛谷题解。

代码语言:javascript
复制
#include <bits/stdc++.h>

using namespace std;

int n,m,u,v;
int ans[100050];
vector<int>e[100050];
void dfs(int x, int d)
{
    if(ans[x]) return ;
    ans[x] = d;
    for(int i = 0; i < e[x].size(); i ++)
    {
        dfs(e[x][i],d);
    }
}
int main()
{
    scanf("%d%d", &n,&m);
    for(int i = 0; i < m; i ++)
    {
        scanf("%d %d", &u, &v);
        e[v].push_back(u);
    }
    for(int i = n; i >= 1; i --)
    {
        dfs(i,i);
    }
    for(int i = 1; i <= n; i ++)
    {
        if(i == 1) printf("%d",ans[i]);
        else printf(" %d",ans[i]);
    }
    printf("\n");
    return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-10-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目描述
  • 输入格式
  • 输出格式
  • 输入输出样例
  • 说明/提示
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档