Codeforces Round #363 (Div. 2) D. Fix a Tree(并查集)
2016-07-21 01:01
465 查看
题目链接:点击打开链接
题目大意:给出一个可能有环的图的父节点序列,要求修改最少的边使其变成一棵树,输出改变次数和改变后的父节点序列。
解题思路:很明显若原图中存在自环,则最小变换次数等于原图中环的个数减1,否则为原图中环的个数。定义一个root,表示变换后的树根。在输入的同时,如果一个点的父节点是其本身,那么把root更新为该点。然后向图中逐条加边,如果出现环,有2种情况
1.若此时root已经存在,那么直接把i连向root
一个栗子:
变换后
2.若此时root不存在,那么将i作为根节点,同时形成一个自环,并把root更新为i,之后的就只会出现情况1了
又一个栗子:
形成自环,并更新root
变换后
题目大意:给出一个可能有环的图的父节点序列,要求修改最少的边使其变成一棵树,输出改变次数和改变后的父节点序列。
解题思路:很明显若原图中存在自环,则最小变换次数等于原图中环的个数减1,否则为原图中环的个数。定义一个root,表示变换后的树根。在输入的同时,如果一个点的父节点是其本身,那么把root更新为该点。然后向图中逐条加边,如果出现环,有2种情况
1.若此时root已经存在,那么直接把i连向root
一个栗子:
变换后
2.若此时root不存在,那么将i作为根节点,同时形成一个自环,并把root更新为i,之后的就只会出现情况1了
又一个栗子:
形成自环,并更新root
变换后
#include <set> #include <map> #include <cmath> #include <stack> #include <queue> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; #define FIN freopen("in.txt", "r", stdin); #define FOUT freopen("out.txt", "w", stdout); #define lson l, mid, cur << 1 #define rson mid + 1, r, cur << 1 | 1 const int INF = 0x3f3f3f3f; const int MAXN = 2e5 + 50; const int MOD = 1e9 + 7; int n, root, cnt, fa[MAXN], par[MAXN]; bool vis[MAXN]; int find(int x) { return par[x] == x ? x : par[x] = find(par[x]); } bool unite(int a, int b) { int x = find(a), y = find(b); if (x == y) return false; par[x] = y; return true; } int main() { #ifndef ONLINE_JUDGE FIN; #endif // ONLINE_JUDGE while (~scanf("%d", &n)) { int root = -1, cnt = 0; for (int i = 1; i <= n; i++) par[i] = i; for (int i = 1; i <= n; i++) { scanf("%d", &fa[i]); if (fa[i] == i) { cnt = -1; root = i; } } for (int i = 1; i <= n; i++) { if (!unite(i, fa[i])) { if (root == -1) root = i; cnt++; fa[i] = root; } } printf("%d\n", cnt); for (int i = 1; i <= n; i++) printf("%d%c", fa[i], " \n"[i == n]); } return 0; }
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- C#递归算法之分而治之策略
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- C#算法之大牛生小牛的问题高效解决方法
- C#算法函数:获取一个字符串中的最大长度的数字
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- 经典排序算法之冒泡排序(Bubble sort)代码
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法