(并查集)Socks CF-731C

题意:k种颜色,n只袜子,m次的要求两只袜子颜色相同,问最小改变袜子颜色使得两只袜子颜色相同的操作次数
题解:一开始想只用并查集做,最后直接输出入集次数,但是这样做等于将整个颜色集合直接混入另一种。
正解:计算每个联通块中最大颜色重复数,分别用联通块里袜子总数减去最大重复数,最后加起来就是答案。
所以我们可以选择用邻接表与标记数组来做,用(map初始化默认为0,数组存不下)map来储存c[i]出现的次数。
或者可以选择并查集压缩连接,然后递推出mx数组,最后用n减去每个mx[i]的值。
代码1:

 #include<bits/stdc++.h>
using namespace std;
const int MAX=2e5+9;
int n,m,k,a[MAX],mx,cnt=0,ans=0,mark[MAX];
map<int,int> mp;
vector<int> g[MAX];
void dfs(int v)
{
    mp[a[v]]++,cnt++,mark[v]=1;
    mx=max(mp[a[v]],mx);
    for (auto u:g[v]) if (!mark[u]) dfs(u);
}
int main()
{
    cin>>n>>m>>k;
    for (int i=0;i<n;i++) cin>>a[i];
    for (int i=0,v,u;i<m;i++) cin>>v>>u,v--,u--,g[v].push_back(u),g[u].push_back(v);
    for (int i=0;i<n;i++) if (!mark[i]) mp.clear(),mx=0,cnt=0,dfs(i),ans+=cnt-mx;
    cout<<ans;
}

代码2:

#include <bits/stdc++.h>
using namespace std;
const int N=200100;
int n,m,k,x,y,v[N],fa[N],mx[N],ans;
map<int,int> mp[N];
inline int ask(int x)
{
    return fa[x]==x?x:fa[x]=ask(fa[x]);
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;++i)
        scanf("%d",&v[i]),fa[i]=i;
    for(int i=1;i<=m;++i)
    scanf("%d%d",&x,&y),fa[ask(x)]=ask(y);
    for(int i=1;i<=n;++i)
    mx[ask(i)]=max(mx[ask(i)],++mp[ask(i)][v[i]]);
    ans=n;
    for(int i=1;i<=n;++i)
    ans-=mx[i];
    printf("%d",ans);
    return 0;
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容