lanqiao OJ 108 发现环

简介: lanqiao OJ 108 发现环

1.发现环 - 蓝桥云课 (lanqiao.cn)

这是一个拓扑排序的题,用dfs找一下拓扑序列,因为找不到所以一定会有环,记录每一个点的前驱点,所求就是答案

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
 
using namespace std ;
const int N = 1e5 +10 ;
struct edge{//用于记录边
  int from , to ;
  edge(int a, int b){
    from = a , to = b ;
  }
};
int n ,cnt;//n是点的数量
bool v[N] ;//记录是否走过这个点
int path[N] ;//最后记录路径
int flag ;//记录一下是否找到环,找到环就退出dfs,要不然死循环
int fa[N] ;//记录每一个节点的前驱节点,便于后面路径的更新
vector<edge> e[N] ;//记录每一条边
 
void dfs(int u ,int pre){
  v[u] = 1 ;//凡是进来的点都标记一下,而且我们每一个点只会走一遍,如果走到第二遍就表示扎到了环
  for(int i = 0 ; i < e[u].size() ; i ++){
    int a = e[u][i].from , b = e[u][i].to ;//起点和终点
    if(b == pre){//因为是无向边所以我们不能再走上一个节点
      continue ;
    }
    fa[b] = a ;//记录一下当前这个点的父节点(前驱节点)
    if(v[b]){//如果找到走了第二次的点,就回溯记录路径
      int tmp = b ;
      flag = 1;//把旗帜标1 , 表示我们已经找到环了,马上退出dfs
      while(1){
        tmp = fa[tmp];
        path[cnt++] = tmp ;
        if(tmp == b) break ;
      } 
      return  ;
    } 
    else dfs(b,a) ;//没有找到环,继续深搜遍历每一个点
    if(flag == 1) return ;
  }
}
 
int main(){
  cin >> n ;
  for(int i = 0 ; i <n ; i ++){
    int a , b ; cin >> a >> b ;//无向图,所以要记录双向
    e[a].push_back(edge(a,b)) ;
    e[b].push_back(edge(b,a)) ;
  }
 
  dfs(1,0) ;
  sort(path,path + cnt) ;//从大到小排序 
  for(int i = 0 ; i < cnt ; i ++) {
    cout << path[i]<< " "  ;
  }
  cout << endl ; 
  return 0 ;
}
相关文章
|
5月前
|
索引
【力扣刷题】两数求和、移动零、相交链表、反转链表
【力扣刷题】两数求和、移动零、相交链表、反转链表
43 2
【力扣刷题】两数求和、移动零、相交链表、反转链表
lanqiao OJ 364 跳石头
lanqiao OJ 364 跳石头
lanqiao OJ 3513 岛屿个数(2023省赛)
lanqiao OJ 3513 岛屿个数(2023省赛)
lanqiao OJ 1030 蓝肽子序列
lanqiao OJ 1030 蓝肽子序列
lanqiao OJ 649 算式900
lanqiao OJ 649 算式900
lanqiao OJ 664 方格填数
lanqiao OJ 664 方格填数
lanqiao OJ 1388 寒假作业
lanqiao OJ 1388 寒假作业