【并查集+贪心】 CodeForces

来源:互联网 发布:做生意的软件 编辑:程序博客网 时间:2024/05/19 10:39

【并查集+贪心】 CodeForces - 731C - Socks


【题目链接】http://codeforces.com/problemset/problem/731/C


题目大意

输入第一行一个zz有n只袜子,要在接下来的m天穿,袜子有k种颜色
第二行是n只袜子的颜色
接下来m行是每天穿的两只袜子的编号

输出至少要改变几只袜子的颜色才能使这个zz不会因为穿了两只不同颜色的袜子而被嘲笑


解题思路

把袜子作为结点,两只同一天穿的袜子连起来,则改变颜色后每个连通图上的袜子颜色要一样。

第一步:并查集找出连通图
第二步:把袜子的颜色存在它的祖先的vector里
第三步:遍历所有大于1的vector,用map找出颜色最多的,剩下的都要改变颜色


AC代码

#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <vector>#include <map>using namespace std;typedef long long LL;const int maxn=200007;int a[maxn];vector <int> v[maxn];int father[maxn];int find_father(int x){    if(x==father[x])        return x;    return father[x]=find_father(father[x]);}void join(int x,int y){    int fx=find_father(x),fy=find_father(y);    if(fx!=fy)    {        father[fy]=fx;    }}int main(){    int n,m,k,i,j,x,y,ans=0;    scanf("%d%d%d",&n,&m,&k);    for(i=1;i<=n;i++)    {        scanf("%d",&a[i]);        father[i]=i;    }    for(i=0;i<m;i++)    {        scanf("%d%d",&x,&y);        join(x,y);    }    for(i=1;i<=n;i++)    {        v[find_father(i)].push_back(a[i]);    }    ans=0;    int mmax=0;    for(i=1;i<=n;i++)    {        if(v[i].size()>1)        {            mmax=0;            map <int,int> m;            for(j=0;j<v[i].size();j++)            {                //printf("v[%d][%d]=%d ",i,j,v[i][j]);                m[v[i][j]]++;                if(mmax<m[v[i][j]]) mmax=m[v[i][j]];            }            ans+=v[i].size()-mmax;        }    }    printf("%d\n",ans);    return 0;}
原创粉丝点击