树 边 : 树边: 树边:深度优先森林中的边。如果结点v是因对(u,v)的探索而首先被发现,则(u,v)是一条树边。
后 向 边 : 后向边: 后向边:后向边(u,v)是将结点u连接到其在深度优先树中一个祖先节点v的边.
(本文我就称之为反向边了,问题不大)
前 向 边 : 前向边: 前向边:是将结点u连接到其在深度优先树中一个后代结点v的边(u,v).
横 向 边 : 横向边: 横向边:指其他所有的边,这些边可以连接同一颗深度优先树中的结点,只要其中一个结点不是另外一个结点的祖先,也可以连接不同深度优先树的两个结点。

其实就是找出无向图中的简单环(不含重边,环内部非相邻点之间没有边)
你找到一个长度大于k的环,直接取不相邻的间隔点按情况1处理即可。
找到长度小于k的环,直接可作为结果按情况2输出。
没找到简单环的情况,就说明这是一颗树,按深度奇偶性分成两部分,取元素多的那一部分按情况一处理。

那么怎么在无向图中找环呢?
其实找到一条指向祖先节点的反向边即可。
如果存在这么一条反向边,那么更新,取深度较大的点连成环(和深度小的点成环有可能环中存在更小的环,即不是简单环)


可以假定图中的深度优先森林有1,2两条不符合树定义的边,2是反向边,与非祖先节点连接的1这条边则是横向边。但我们在深度优先遍历找环的过程中其实是不会碰到横向边的,(如果有这条边,也己经成为了树边)。所以怎么利用这个性质呢?可以发现我在深度遍历过程中用到了一个随放随扔的vector,它可以维护根节点到当前点的路径。那么如果找到一个点深度比当前点小于1以上,即可表示从该点到当前可以连接成环(不一定是简单环),我们取max的作用就是为了防止取到的是一个非简单环,取完max就可以保证简单环了.

 for(auto it:e[x]){if(dep[it]){if(dep[x]-dep[it]>1){flag=max(dep[it],flag);}}}

然后这里dfs中在当前点找环和进行子树遍历的顺序也很重要,一定要优先在当前节点找环,之后才进行子树的判定.不然也可能会出现非简单环的情况。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define MAXN 500005
#define rep(n) for(int i=1;i<=n;i++)
#define rall(x) for(int i=(x).size()-1;i>=0;i--)
#define all(x) for(int i=0;i<(x).size();i++)
vector<int>e[MAXN];
int dep[MAXN];
vector<int>sta;
vector<int>ans;
int n,m,k;
vector<int>col[2];
void dfs(int x)
{if(ans.size())return;col[dep[x]%2].push_back(x);sta.push_back(x);int flag=-1;for(auto it:e[x]){if(dep[it]){if(dep[x]-dep[it]>1){flag=max(dep[it],flag);}}}if(flag!=-1){for(int i=flag;i<=dep[x];i++)ans.push_back(sta[i-1]);return ;}for(auto it:e[x]){if(!dep[it]){dep[it]=dep[x]+1;dfs(it);}}sta.pop_back();}
int main()
{scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=m;i++){int u,v;scanf("%d%d",&u,&v);e[v].push_back(u);e[u].push_back(v);}dep[1]=1;dfs(1);if(ans.size()==0){if(col[0].size()<col[1].size())swap(col[0],col[1]);for(int i=0;i<(k+1)/2;i++)ans.push_back(col[0][i]);printf("1\n");} else{vector<int>tmp;if(ans.size()>k){printf("1\n");for(int i=0;i<(k+1)/2;i++)tmp.push_back(ans[2*i]);ans.assign(tmp.begin(),tmp.end());}else{printf("2\n%d\n",ans.size());}}for(auto it:ans){if(it!=*ans.begin())putchar(' ');printf("%d",it);}
}

Codeforces Round 649 (Rated for Div. 2)D. Ehab s Last Corollary详细题解(图论+简单环)相关推荐

  1. Educational Codeforces Round 114 (Rated for Div. 2) (A ~ F)全题解

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Educational Codeforces Round 114 (Rated for Div. 2) ...

  2. Educational Codeforces Round 106 (Rated for Div. 2)(A ~ E)题解(每日训练 Day.16 )

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 Educational Codeforces Round 106 (Rated for Div. ...

  3. Educational Codeforces Round 37 (Rated for Div. 2) 1

    Educational Codeforces Round 37 (Rated for Div. 2) A.Water The Garden 题意:Max想给花园浇水.花园可被视为长度为n的花园床,花园 ...

  4. Educational Codeforces Round 90 (Rated for Div. 2)(A, B, C, D, E)

    Educational Codeforces Round 90 (Rated for Div. 2) Donut Shops 思路 分三种情况: a==c/ba == c / ba==c/b这个时候两 ...

  5. Educational Codeforces Round 89 (Rated for Div. 2)(A, B, C, D)

    Educational Codeforces Round 89 (Rated for Div. 2) A. Shovels and Swords 思路 题意非常简单,就是得到最多的物品嘛,我们假定a, ...

  6. Educational Codeforces Round 114 (Rated for Div. 2) D. The Strongest Build 暴力 + bfs

    传送门 文章目录 题意: 思路: 题意: 你有nnn个装备槽,每个槽里面有cic_ici​个力量加成,对于每个槽只能选一个力量加成,现在给你mmm个力量组合[b1,b2,...,bn][b_1,b_2 ...

  7. Educational Codeforces Round 72 (Rated for Div. 2) D. Coloring Edges dfs树/拓扑找环

    传送门 文章目录 题意: 思路: 题意: 给你一张图,你需要给这个图的边染色,保证如果有环那么这个环内边的颜色不全相同,输出染色方案和用的颜色个数. n,m≤5e3n,m\le5e3n,m≤5e3 思 ...

  8. Educational Codeforces Round 111 (Rated for Div. 2) D. Excellent Arrays 组合数学

    传送门 文章目录 题意: 思路: 题意: 给你一个数组aia_iai​,定义一个数组是好的当且仅当对于所有iii都有ai!=ia_i!=iai​!=i.定义f(a)f(a)f(a)表示数组aaa中i& ...

  9. Educational Codeforces Round 111 (Rated for Div. 2) E. Stringforces 二分 + 状压dp

    传送门 文章目录 题意: 思路: 题意: 给你一个串,只包含前kkk个字母和???,定义fif_ifi​表示第iii个字母在串中出现的最长连续长度,你现在需要将???替换为前kkk个字母,使得mini ...

最新文章

  1. select元素的各种jquery修改获取添加方法
  2. 计算机应用技术商务网站运营,计算机应用技术云计算与商务网站运营有什么区别...
  3. vivo应用商店电脑版_VIVO应用商店代理商江湖的那些关系
  4. adobe怎么统计字数_SEO技能:怎么写站内文章对网站排名更好?
  5. Dell Inspiron 6400上安装Fedora 5后使声卡义务正常的方法
  6. 1342.将数字变成0的操作次数
  7. 微信小程序支付异常:requestPayment:fail no permission
  8. python脚本入门_python 脚本学习(一)
  9. 一步一步理解拖拽Drag(四)
  10. 判断点在多边形内部的方法(Java版)
  11. 虚机使用技巧几则(经验交流)
  12. 安居客 Android 项目架构演进
  13. SpringMVC-视图和视图解析器
  14. GBase 8c 备份控制函数(四)
  15. 使用命令结束Linux系统
  16. 微图影像地图导出拼接大图的参数说明
  17. 服务器该不该选SSD硬盘储存?
  18. IOS 最右 注册 登录协议分析记录
  19. 苹果不创新,库克有道理
  20. 经典小游戏(密室逃脱全集+答案)

热门文章

  1. 安卓手机运行linux
  2. 【排行榜】Carla leaderboard 排行榜 运行与参与手把手教学
  3. C# DataGridView控件选中某行和获取单元格数据
  4. 了解一下,Android 10 Build系统
  5. mac 下安装brew
  6. 解决iOS UITableView分组header悬浮,每个section header上面有一段空白间距
  7. Codeforces Round #571 (Div. 2)
  8. Mysql查看表的数据量
  9. 聚类算法——kmeans和meanshift
  10. Java的Map(映射)特性及编程思想