【CF698B】B. Fix a Tree(并查集,贪心)

10 篇文章 0 订阅
8 篇文章 0 订阅

修树

题意:

  • 给你一颗树的 边 关系( i 点 与 P i P_i Pi 之间有一条边 ),有可能 边 关系有错,问你用最少的更改次数让这颗树合法,输出更改后的 关系。
  • 如果 i = = P i i == P_i i==Pi ,表示这个点是根节点。

思路:

  • 贪心,本来已经合法的关系我们显然不需要变动,先连结。标记所有合并过程中不合法的关系。
  • 之后对于不合法的关系,我们找到一个合法的(也就是和它不在同一个连通块中,因为在同一个块中再加一条边就存在环了,不合法)其他块与它连结。
  • 如果暴力找的话会 n 2 n^2 n2 超时,可以用双指针优化这过程。

C o d e : Code: Code:

#include<bits/stdc++.h>
#include<unordered_map>
#define mem(a,b) memset(a,b,sizeof a)
#define cinios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define sca scanf
#define pri printf
#define forr(a,b,c) for(int a=b;a<=c;a++)
#define rfor(a,b,c) for(int a=b;a>=c;a--)
#define all(a) a.begin(),a.end()
#define oper(a) (operator<(const a& ee)const)
#define endl "\n"
using namespace std;

typedef long long ll;
typedef pair<int, int> PII;

double DNF = 1e17;
const int N = 200010, M = 200010, MM = 110;
int INF = 0x3f3f3f3f, mod = 1e9 + 7;
ll LNF = 0x3f3f3f3f3f3f3f3f;
int n, m, k, T, S, D, K;
int z[N], p[N];
bool st[N];

int find(int x) {
	return p[x] == x ? p[x] : p[x] = find(p[x]);
}

void solve() {
	cin >> n;
	forr(i, 1, n)cin >> z[i], p[i] = i;

	int id = -1, cnt = 1, res = 0;

	forr(i, 1, n) { //合并所有合法边
		int fa = find(i), fb = find(z[i]);
		if (i == z[i]) {
			if (id == -1)id = i;//根节点只能有一个
			else st[i] = true;
		}
		else if (fa ^ fb) {
			p[fa] = fb;
		}
		else st[i] = true;
	}

	forr(i, 1, n) { //再处理不合法
		if (st[i]) { 
			while (find(cnt) == i)cnt++;//找到不在同一块的点

			if (cnt > n)cnt = i;
			//这里需要特判下根节点,如果怎么都找不到证明这个点是根节点

			z[i] = cnt;
			p[find(i)] = find(cnt);
			res++;
		}
	}

	cout << res << endl;
	forr(i, 1, n)cout << z[i] << ' ';
}

int main() {
	cinios;
	T = 1;
	while (T--)solve();
	return 0;
}
/*
7
4 3 2 6 3 5 2
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值