图论问题集合

图论问题集合

寻找特殊有向图(一个节点最多有一个出边)中最大环路问题

我们以力扣2360. 图中的最长环为例解决这个问题

特殊有向图解析

任意一个图,都是由若干连通块组成,连通块之间并不相连。

对于连通块上的每一个节点:

复制代码
1、最多只能有一个出边;
2、其中任意一个节点N,他只有这一个出边,他要么和前面的节点连上构成一个整体的连通体;要么和身后连接他的其中一个节点连上构成环路。
3、所以说不存在一个连通体中存在两个环:即任意一个连通体中,最多只有一个环
4、对于图中任意一个大小为 m 的连通块,有 m 个点,每个点至多出去一条边,所以连通块至多有 m 条边。
5、m 个点 m−1 条边的连通图是一棵树,在树上增加一条有向边,至多会形成一个环。(这样的图叫做内向基环树)

算法解析

通过上面分析,这种特殊的有向图,每一个连通块中至多有一个环,题目最终让我们找一个最大的环:

所以我们只需要挨个遍历图中每一个连通块,找到各个连通块当中环的大小,并动态维护最大值即可。

步骤 1 :举例分析如何在一个连通块中找到环并使用时间戳计算大小

1、我们类比生活场景,观察下图,我们从0点开始走,只要不走到死胡同(题中会指向点-1)或者遇到之前走过的点,我们就继续前进,当我们发现我又走回了曾经到过的点,就说明一定存在环;如果我们直到最终走到死胡同的时候都没走回头路,说明没有环,可以继续看下一个连通体。

2、假设我们是time=2的时候,第一次到节点3,time=3到达节点2,time=4到达节点4,time=5的时候我们发现,节点3我们在time=2的时候来过一次,说明存在环,环的大小恰好等于时间差,即:5-2=3,共三个节点。

步骤 2 :抽象成算法

1、对于一个新的连通体而言,我们第一次来,只要没走到头或者走回头路,我们就持续前进,并记录走到该处的时间;

2、当走到死胡同,说明没有环,继续下一个连通体;当走到之前访问过的点时,利用时间差计算这个连通体中环的大小

3、遍历完所有连通体,动态维护最大的环大小。

4、实现的时候,我们从头到尾遍历所有点,从任意入口进入连通体;当这个连通体环路被处理完,但是程序又从别的入口进入该连通体(上面图中,0、2、3、4都已经处理完,程序又从1进入),这种情况我们直接跳过就行。

注意

复制代码
本题保证每个连通块至多有一个环,所以可以根据时间差算出环长。如果没有这个保证,时间差算出的可能不是最长环。一般图的最长环是 NP-hard 问题。

实现

cpp 复制代码
class Solution {
public:
	int longestCycle(vector<int>& edges) {
		int n = edges.size();
		int ans = -1;
		vector<int> visit(n);//记录第一次访问时间
		int cur_time = 1;//记录当前时间
		//遍历每个节点,其实这里是遍历每个连通体,从连通体上任意一个点进入,然后处理完一个连通体之后,已经走过的点不走,一直到新的点
		//如果新的点依旧是属于已访问过的连通体,则直接跳过,反之说明到了新的连通体,继续处理
		for (int i = 0; i < n; i++) {
			int x = i;//记录当前节点
			//将初始时间进行记录,如果该环被处理过,则任意一个处理过的点第一次访问时间要小于这次的开始时间
			int start_time = cur_time;
			while (x != -1 && visit[x] == 0) {//只要没走到死胡同(值==-1)并且是没经过的点,就一直走
				visit[x] = cur_time++;//因为保证了走的是没经过的点,所以保证这里的值是第一次访问时间
				x = edges[x];
			}
			if (x != -1 && visit[x] >= start_time) {//退出循环之后,确认不是走到死胡同&&这个环路没被处理过(这轮循环的开始时间大于该点第一次访问时间,说明该点之前被处理过)
				//此时cur_time 表示第二次到达x时间-visit[x]第一次到x时间
				ans = max(ans, cur_time - visit[x]);//在所有的环中,也就是所有的连通体中可能存在的所有环,找最大的。
			}
		}
		return ans;
	}
};
相关推荐
KyollBM3 小时前
【图论】分层图 / 拆点
图论
GawynKing6 小时前
图论(5)最小生成树算法
算法·图论·最小生成树
KarrySmile7 小时前
Day60--图论--94. 城市间货物运输 I(卡码网),95. 城市间货物运输 II(卡码网),96. 城市间货物运输 III(卡码网)
图论·spfa·bellman_ford·队列优化·最短路算法·负权回路·单源有限最短路
花开富贵ii12 小时前
代码随想录算法训练营四十三天|图论part01
java·数据结构·算法·深度优先·图论
yi.Ist1 天前
图论——Djikstra最短路
数据结构·学习·算法·图论·好难
KarrySmile1 天前
Day55--图论--107. 寻找存在的路径(卡码网)
图论·并查集·寻找存在的路径
KarrySmile1 天前
Day62--图论--97. 小明逛公园(卡码网),127. 骑士的攻击(卡码网)
图论·floyd·floyd算法·弗洛伊德算法·astar算法·小明逛公园·骑士的攻击
Morriser莫2 天前
图论Day2学习心得
算法·图论
KarrySmile2 天前
Day53--图论--106. 岛屿的周长(卡码网),110. 字符串接龙(卡码网),105. 有向图的完全联通(卡码网)
深度优先·图论·广度优先·广搜·岛屿的周长·字符串接龙·有向图的完全联通
zyd09152 天前
代码随想录Day50:图论(图论理论、深度搜索理论、所有可达路径、广度搜索理论)
java·数据结构·算法·leetcode·图论