博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【CodeForces 699D】Fix a Tree
阅读量:6958 次
发布时间:2019-06-27

本文共 946 字,大约阅读时间需要 3 分钟。

dfs找出联通块个数cnt,当形成环时,令指向已访问过节点的节点变成指向-1,即做一个标记。把它作为该联通图的根。

把所有联通的图变成一颗树,如果存在指向自己的点,那么它所在的联通块就是一个树(n-1条边),选择这样一个点,其它联通块的根指向它,就需要cnt-1次改变。如果都是环(没有指向自己的),那任意选定一个环,拆开,其它环拆开再连到此环上,就需要cnt次改变。

#include 
#define N 200005int a[N],v[N],h[N],fa[N],q[N],ans,cnt,ba;int dfs(int u){ v[u]=cnt; if(!v[a[u]])return a[u]=dfs(a[u])==-1?a[u]:a[a[u]]; if(v[a[u]]==cnt&&a[u]!=u)return a[u]=-1;//指向的是本次dfs内访问的点,即形成环 return a[u]=a[a[u]]==-1?a[u]:a[a[u]];//可能是-1即是前面的拆环点}int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); fa[i]=a[i]; if(a[i]==i)ba=i; } for(int i=1;i<=n;i++) if(!v[i]){ cnt++;//第cnt次dfs dfs(i); if(++h[a[i]]==1) ans++;//联通块个数 } printf("%d\n",ans-(ba>0)); for(int i=1;i<=n;i++) //拆环点(-1),或者不是总根的树根,是需要改变的。 if(a[i]==-1||i==a[i]&&i!=ba)printf("%d ",ba?ba:ba=i);//ba为0则选定i为总的根。 else printf("%d ",fa[i]);//不改变}  

 

转载地址:http://ctmil.baihongyu.com/

你可能感兴趣的文章
SElinux以及防火墙的关闭
查看>>
android中dip、dp、px、sp和屏幕密度
查看>>
MySQL 可以用localhost 连接,但不能用IP连接的问题
查看>>
linux学习(之二)-初识linux的一些常用命令
查看>>
linux基础系统管理---系统管理
查看>>
重启网络出现RTNETLINK answers: File exists问题解决
查看>>
清空微信浏览器缓存debug页面清除法
查看>>
组策略 之 正确理解STARTER GPO
查看>>
分布式搜索elasticsearch的5种分片查询优先级
查看>>
python + selenium 弹出Alert提示窗, 自动确认。python语法注意
查看>>
PHP htmlspecialchars和htmlspecialchars_decode(函数)
查看>>
adt-bundle-windows-x86 出现的问题
查看>>
VHD and BitLocker
查看>>
我的友情链接
查看>>
菊花新
查看>>
OpenCASCADE Conic to BSpline Curves-Circle
查看>>
cacti监控
查看>>
ocp 052最新题库分享 20180530 又一次变题
查看>>
数据结构之二叉树(前序 中序 后续线索话非递归方式)
查看>>
CSS选择器
查看>>