题目链接:
http://codeforces.com/problemset/problem/698/B
题解:
还是比较简单的。因为每个节点只有一个父亲,可以直接建反图,保证出现的环中只有一条路径。
然后发现,有多少个环,就需要改多少条边。然后设出现连向自己的节点为x,这些也要改边,对答案的贡献应为:$max(x-1,0)$。对于最后的根节点,有自环选一个,没自环在其他环上任选一个点就行。
#include<cstdio>
inline int min(int a,int b){return a<b?a:b;}
inline int read(){
int s=;char ch=getchar();
while(ch<''||ch>'') ch=getchar();
while(ch>=''&&ch<='') s=s*+(ch^),ch=getchar();
return s;
}
const int N=;
int n;
int p[N];
int dfn[N],low[N],dfx,stk[N],top,scc;
bool instk[N];
int size[N];
int first[N];
inline void tarjin(int x){
dfn[x]=low[x]=++dfx;
stk[++top]=x;instk[x]=true;
if(!dfn[p[x]]){
tarjin(p[x]);
low[x]=min(low[x],low[p[x]]);
}else if(instk[p[x]]) low[x]=min(low[x],dfn[p[x]]);
if(low[x]==dfn[x]){
int t;scc++;
do{
t=stk[top--];
size[scc]++;
if(!first[scc])
first[scc]=t;
instk[t]=false;
}while(t!=x);
}
}
int main(){
n=read();
for(int i=;i<=n;i++){
p[i]=read();
}
int ans=;
int to=;
for(int i=;i<=n;i++)
if(p[i]==i){ ans--;break;}
for(int i=;i<=n;i++){
if(!dfn[i])
tarjin(i);
if(p[i]==i&&!to)
to=i;
}
if(!to){
to=p[first[]]=first[];
}
for(int i=;i<=scc;i++){
if(size[i]>||(first[i]==p[first[i]]&&size[i]==)){
p[first[i]]=to;
ans++;
}
}
printf("%d\n",ans);
for(int i=;i<=n;i++)
printf("%d%c",p[i],i<n?' ':'\n');
}
【codeforces 698B】 Fix a Tree的更多相关文章
-
【27.48%】【codeforces 699D】 Fix a Tree
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
-
【CodeForces 699D】Fix a Tree
dfs找出联通块个数cnt,当形成环时,令指向已访问过节点的节点变成指向-1,即做一个标记.把它作为该联通图的根. 把所有联通的图变成一颗树,如果存在指向自己的点,那么它所在的联通块就是一个树(n-1 ...
-
【27.91%】【codeforces 734E】Anton and Tree
time limit per test3 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
-
【codeforces 791D】 Bear and Tree Jumps
[题目链接]:http://codeforces.com/contest/791/problem/D [题意] 你可以从树上的节点一次最多走k条边. (称为跳一次); 树为无权树; 然后问你任意两点之 ...
-
【并查集】【模拟】Codeforces 698B &; 699D Fix a Tree
题目链接: http://codeforces.com/problemset/problem/698/B http://codeforces.com/problemset/problem/699/D ...
-
【19.27%】【codeforces 618D】Hamiltonian Spanning Tree
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
-
【Codeforces 1086B】Minimum Diameter Tree
[链接] 我是链接,点我呀:) [题意] 题意 [题解] 统计叶子节点个数m 把每条和叶子节点相邻的边权设置成s/cnt就可以了 这样答案就是2*s/m(直径最后肯定是从一个叶子节点开始,到另外一个叶 ...
-
【Codeforces 161D】Distance in Tree
[链接] 我是链接,点我呀:) [题意] 问你一棵树上有多少条长度为k的路径 [题解] 树形dp 设 size[i]表示以节点i为根节点的子树的节点个数 dp[i][k]表示以i为根节点的子树里面距离 ...
-
【CodeForces 614A】Link/Cut Tree
题 题意 给你一个区间,求里面有多少个数是k的次方. 分析 暴力,但是要注意这题范围会爆long long,当k=1e8: l=1:r=1e18时 k²=1e16,判断了是≤r,然后输出,再乘k就是1 ...
随机推荐
-
LRU页面置换算法
本文以序列长度20的{ 7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1};以及页面4:为例: #include <stdio.h> #define Init ...
-
POJ做题笔记:1000,1004,1003
1000 A+B Problem 题目大意:输入两个数a和b,输出他们的和. 代码: #include <stdio.h> int main() { int a, b; while (sc ...
-
利用css做扇形
html和css每一块的边边角角都是直来直去,除了border-raius,要怎么做扇形了?当然,你如果只想要得到直角扇形,和半圆,那就很简单?那么做小于180的直角扇形,如何做了(大于180的直角无 ...
-
长理ACM 14-星期几(谌海军)
题目描述:编一个程序,已知今天是星期几,计算出n天后是星期几.要求使用枚举变量. 输入描述:输入为两个正整数,第一个数n(n<=6)表示今天是星期几,第二个数m(m<=1000),表示求m ...
-
iscsiadm用法简介
已知192.168.14.112节点,存在目标器 iqn.2015.06.cn.hrbyg.www.ygcs.c0a802b8:wzg,未设置CHAP,存在目标器 iqn.2015.06.cn.hrb ...
-
Mobile Matrices
This is an attempt to compile a list of relevant specifications for all modern smart phones and mobi ...
-
php随笔4-thinkphp 学习-ThinkPHP3.1快速入门(2)数据CURD
ThinkPHP3.1快速入门(2)数据CURD 浏览:194739 发布日期:2012/09/05 分类:文档教程 关键字: 快速入门 CURD 上一篇中,我们了解了ThinkPHP的基础部分, ...
-
Javascript实战开发:教你使用raphael.js绘制中国地图
最近的数据统计项目中要用到中国地图,也就是在地图上动态的显示某个时间段某个省份地区的统计数据,我们不需要flash,仅仅依靠raphael.js以及SVG图像就可以完成地图的交互操作.在本文中,我给大 ...
-
外部访问docker中的MySQL
注:192.168.1.203机器上装有docker,容器在该机器上 mysql> use mysql; mysql> update user set authentication_str ...
-
xslt 2.0 分组
把数据拆成200个一组 <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet vers ...