题目链接:图的遍历

本题是一个有向图,要求每个点能到达的编号最大的点。由于是有向图,如果直接DFS如果有环就可能忽略一些点,所以我们可以直接缩点

缩点之后

  • 在同一个强联通分量中的点可以相互到达,那么我们可以在缩点时记录每个联通分量中编号最大的点
  • 一个强联通分量中所有点能到达的最大编号的点即为这个联通分量能到达的最大的编号

然后由于太麻烦了还是算了。

次数少的dfs错的原因是因为当出现强连通分量的时候环中最先遍历的点的最大值无法更新 所以有人缩点 多次dfs也可以解决这个问题

本题正确解法应该是反向建边+直接DFS。
因为题目要求求能到达的最大的点,直接DFS会导致大的值无法更新后面的环,但是如果我们反向建边,并且从编号最大的点开始倒序循环 ,直接从编号大的点到达编号小的点,并直接更新答案数组,因为后面的点都比当前的点小,所以直接就是答案,并以判断是否更新过来躲避环。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<math.h>
#include<cstring>
#include<bitset>
#include<vector>
#include<queue>
#define ls (p<<1)
#define rs (p<<1|1)
#define over(i,s,t) for(register int i = s;i <= t;++i)
#define lver(i,t,s) for(register int i = t;i >= s;--i)
//#define int __int128
#define lowbit(p) p&(-p)
using namespace std;typedef long long ll;
typedef pair<int,int> PII;
const int INF = 0x3f3f3f3f;
const int N = 1e5+7;//点数
const int M = 5e5+7;//边数int n,m,a[N];
vector<int>G[N];void dfs(int u,int fa){if(!a[u])a[u] = fa;for(int i = 0;i < G[u].size();++i){int v = G[u][i];if(a[v])continue;dfs(v,fa);}
}int main()
{scanf("%d%d",&n,&m);over(i,1,m){int x,y;scanf("%d%d",&x,&y);G[y].push_back(x);}lver(i,n,1)dfs(i,i);over(i,1,n)printf("%d ",a[i]);puts("");return 0;
}

贴一下大佬的TarjanTarjanTarjan缩点
来源

/*
缩点
在缩完点的图上dfs
*/
#include <cstdio>
#include <cstring>
#include <iostream>#define maxn 100010using namespace std;inline int read() {int op = 1, a = 0;char c = getchar();for (; c < '0' || c > '9'; c = getchar()) if (c == '-') op = -1;for (; c >= '0' && c <= '9'; c = getchar()) a = a * 10 + c - '0';return op * a;
}int n, m;int cnt;
int head[maxn];
struct Edge {int from, to, nxt;} e[maxn];inline void add_edge(int u, int v) {cnt++;e[cnt].to = v;e[cnt].from = u;e[cnt].nxt = head[u];head[u] = cnt;
}int r;//栈的右端点
int s[maxn];//数组来模拟栈
int num;//个数
int Time;
bool vis[maxn];
int belong[maxn];//一个点属于哪个强连通分量
int dfn[maxn], low[maxn];
int rep[maxn];//存储缩完点后每个点所代表的所有点中编号最大的 void Tarjan(int u) {dfn[u] = low[u] = ++Time;vis[u] = 1;s[++r] = u;int R = r;for (int i = head[u]; i; i = e[i].nxt) {int v = e[i].to;if (!dfn[v]) {Tarjan(v);low[u] = min(low[u], low[v]);}else if (vis[v]) low[u] = min(low[u], dfn[v]);}if (dfn[u] == low[u]) {num++;for (int i = R; i <= r; i++) {vis[s[i]] = 0;belong[s[i]] = num;rep[num] = max(rep[num], s[i]);//记录强连通分量中编号最大的点(的编号) }r = R - 1;}
}//重新建图
void rebuild() {cnt = 0;memset(head, 0, sizeof head);for (int i = 1; i <= m; i++) {int x = e[i].from, y = e[i].to;if (belong[x] == belong[y]) continue;add_edge(belong[x], belong[y]);}
}int ans[maxn];void dfs(int u) {if (ans[u]) return;ans[u] = rep[u];//必定能到这个强连通分量中的点 for (int i = head[u]; i; i = e[i].nxt) {int v = e[i].to;dfs(v);ans[u] = max(ans[u], ans[v]);//和上一句的位置不能颠倒 }
}int main() {n = read(), m = read();for (int i = 1; i <= m; i++) {int x = read(), y = read();add_edge(x, y);}for (int i = 1; i <= n; i++) if (!dfn[i]) Tarjan(i);rebuild();for (int i = 1; i <= num; i++) if (!ans[i]) dfs(i);for (int i = 1; i <= n; i++) cout << ans[belong[i]] << ' ';//一个点的答案都直接输出对应的强连通分量能到的编号最大的点 return 0;
}

解题报告:luogu P3916 图的遍历( 缩点 + DFS ? × 思维 + 反向建边 + DFS √ )相关推荐

  1. P3916 图的遍历

    题目传送门 今晚闲游洛谷,在图论中发现了这独树一帜的记忆化搜索.看到这道题,第一感受就是DFS,每一个点DFS一遍,如果能更新就更新,但是这样的时间复杂度是O(nm),对于1≤N,M≤105的数据显然 ...

  2. 图的遍历c语言数据结构实验报告,数据结构实验报告--图的遍历

    江 西 理 工 大 学 数据结构 实验报告 实验名称 图的遍历 日期 2014-12-01 专业班级 计算机(中加)131班 地点 信息学院621 实验人 王鹏伟 学号 同组人 单独完成 152013 ...

  3. 图论——图的遍历(洛谷 P3916)

    题目选自洛谷P3916 反向建边 + dfs 按题目来每次考虑每个点可以到达点编号最大的点,不如考虑较大的点可以反向到达哪些点 循环从N到1,则每个点i能访问到的结点的A值都是i 每个点访问一次,这个 ...

  4. c++ 遍历所有点且距离最短_L3图论第08课 图的遍历

    L3-图论-第08课 图的遍历 图的遍历是指,从给定图中任意指定的顶点(称为初始点)出发,按照某种搜索方法沿着图的边访问图中的所有顶点,使每个顶点仅被访问一次,这个过程称为图的遍历.遍历过程中得到的顶 ...

  5. 2014百度之星资格赛解题报告:能量变换

    QAZ的能量变换 题目描述: 魔法师百小度也有遇到难题的时候-- 现在,百小度正在一个古老的石门面前,石门上有一段古老的魔法文字,读懂这种魔法文字需要耗费大量的能量和大量的脑力. 过了许久,百小度终于 ...

  6. 图的遍历c语言数据结构实验报告,数据结构图的遍历实验报告.doc

    数据结构图的遍历实验报告.doc 实 验 报 告课程名称 数据结构实验名称 图的遍历姓 名专 业 计算机科学与技术班 级 计算机学 号成绩计算机科学与技术学院实验教学中心2015 年 11 月 20 ...

  7. 久久未至的Codevs1024一塔湖图解题报告

    一直想给这个题写个解题报告但是给忘了OTZ难产了这么久终于出来了 这个题当时坑了我一个星期整,所以一定要写一个解题报告纪念一下 1024 一塔湖图 时间限制: 1 s 空间限制: 128000 KB ...

  8. 【割边缩点】解题报告:POJ - 3694 - Network(Tarjan割边缩点 + LCA + 并查集优化)

    POJ - 3694 - Network 给定一张N个点M条边的无向连通图,然后执行Q次操作,每次向图中添加一条边,并且询问当前无向图中"桥"的数量.N≤105,M≤2∗105,Q ...

  9. 《数据结构》实验报告六:图的表示与遍历

    一.实验目的 1.掌握图的邻接矩阵和邻接表表示 2.掌握图的深度优先和广度优先搜索方法 3.理解图的应用方法 二.实验预习  说明以下概念 1.深度优先搜索遍历: 一种图的遍历方式:从图中任意一个起始 ...

最新文章

  1. 用puthivestreaming把hdfs里的数据流到hive表
  2. 笑傲江湖ol更新服务器正在维护,笑傲江湖ol4月22日更新内容 调整死亡复活设置...
  3. 面向对象——构造方法(重载)
  4. 网站集成PayPal如何设置
  5. Apace、Ngnix、Tomcat三者关系
  6. Linux下C编程入门(.h文件,.c文件,以及多文件调用的方式)
  7. Oracle对表空间操作的sql
  8. html5和html的区别是什么?学HTML5要不要学html?
  9. [转]centos7.2 下 nginx 开机启动
  10. 计算机辅助设计技术案例,【智能科技学院】学院前沿技术运用课程组开展“计算机辅助设计”专题讲座...
  11. 你是愛我還是需要我?
  12. Spring Boot + Spring-Kafka 异步配置
  13. 一体机or复合机?企业文印设备该怎么选
  14. 设计模式相关书籍推荐
  15. office 2016 官方完整版
  16. 鸿蒙os2021升级日程,消息称华为EMUI 11.1三月上线:更... - @是Ustinian鸭 的微博精选 - 微博国际站...
  17. 树莓派小车————全部代码
  18. Ajax入门介绍篇:Ajax开发基础
  19. linux下开启rpcbind服务
  20. 老人与海好词100英文带翻译_The_Old_Man_and_The_Sea_老人与海_中英文对照版_(good)

热门文章

  1. 【iOS】控件截图、MP4格式视频流和m3u8格式视频流截取某一帧功能的实现
  2. textlive在安装完winedt的配置问题
  3. 通过案例学功能 自定义监控功能初探
  4. linux系统安全优化
  5. String.fromCharCode()
  6. Linux 高可用(HA)集群之keepalived+lvs
  7. windows域设计best practice
  8. 327 - Evaluating Simple C Expressions
  9. mysql installer图解_MySQL Installer GUI - 图解
  10. js调用数科阅读器_阅读大型 JavaScript 源码时有什么好用的工具?