[树] cf 698B D Fix a Tree
2016-07-20 10:59
281 查看
题意
给定每个节点的父亲,判断是否为一棵有根树;若不是,改变最少的节点的父亲,使其成为有根树。(节点规模2*105)。题目分析
比赛时一脸懵逼,后来看了大神代码——本题就是“见招拆招”:从叶子(尚未访问过的节点)往上找其最远的祖先,若能找到根,则合题;若找到环或找到与树不连通的祖先,则将祖先的父亲指向根。代码中dep[i]代表i是第几批被访问的。
代码
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<map> #include<algorithm> using namespace std; const int maxn=2e5+5; int a[maxn]; int root=0; int dep[maxn]={0}; int cnt=0; int ans; void work(int x) { dep[x]=++cnt; while(dep[a[x]]==0) x=a[x],dep[x]=cnt; if(dep[a[x]]==cnt)//祖先是当前批次,则有可能是环、不连通 { if(root==0) root=x; if(a[x]!=root)//祖先是环或不连通 a[x]=root,ans++; } } int main() { int n; cin>>n; for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) if(a[i]==i) root=i; for(int i=1;i<=n;i++) if(dep[i]==0) work(i); cout<<ans<<endl; for(int i=1;i<n;i++) printf("%d ",a[i]);cout<<a <<endl; return 0; }
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- C#递归算法之分而治之策略
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- C#算法之大牛生小牛的问题高效解决方法
- C#算法函数:获取一个字符串中的最大长度的数字
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现获取系统目录并以Tree树叉显示的方法
- C#实现的算24点游戏算法实例分析
- 经典排序算法之冒泡排序(Bubble sort)代码
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C语言实现输入一颗二元查找树并将该树转换为它的镜像
- C++实现一维向量旋转算法