NC22562 抓捕盗窃犯(个人并查集做法)

抓捕盗窃犯 (nowcoder.com)NC22562 抓捕盗窃犯(个人并查集做法)https://ac.nowcoder.com/acm/problem/22562

总体思路:

将每个可连通的地点均放入在同一个集合中,再求出每个集合中包括的人数,取最大的M个集合求和,时间复杂度o(N)


代码核心:

遍历1~n个地点,将i与v[i]合并,为了保证fa[i]与fa[v[i]]相同,选择将较大的地点合并到较小的地点。由于从1开始遍历,可连通的地点i的fa[i]一定为在其集合中的最小值,从而保证了一致性

	for(int i=1;i<=n;i++) merge(max(i,v[i]),min(v[i],i));

完整代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int fa[N],v[N];
ll a[N],s[N];
int find(int x)
{
	return (fa[x]==x?x:fa[x]=find(fa[x]));
}
void merge(int x,int y)
{
	fa[find(x)]=find(y);
}
void solve()
{
	int n,m;
	ll ans=0;
	cin>>n>>m;
	for(int i=1;i<=n;i++) fa[i]=i;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) cin>>v[i];
	for(int i=1;i<=n;i++) merge(max(i,v[i]),min(v[i],i));
	for(int i=1;i<=n;i++) s[find(i)]+=a[i];
	sort(s+1,s+n+1);
	while(m--)
	{
		ans+=s[n];
		n--;
	}
	cout<<ans;
}
int main()
{
	solve();
	return 0;
}

上一篇:【leetcode】832. 翻转图像(flipping-an-image)(模拟)[简单]


下一篇:带修莫队