【2018 计蒜之道 复赛】计蒜客 贝壳找房魔法师顾问

需要注意的问题是修改是可以传递的,也就是如果 1 能改成 2 2 能改成 3 ,那么 1 就能改成 3
如果两个串都是可修改的比较简单,只需要用并查集维护可以相互修改的元素就可以了。
如果只有一个串是可修改的,相当于边是有向边,不难证明如下结论:对每个连通块,如果它有环,那么需要多加一条边。否则和无向图是一样的。

#include<cstdio>
#include<cstring>
#include<set>
#include<algorithm>
#include<vector>
using namespace std;
set<pair<int,int> > s;
vector<int> to[100010],bel[100010];
int a[100010],b[100010],fa[100010],n,v,ord[200010],que[100010],in[100010],hd,tl,tot;
char s1[100],s2[100];
int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
int main()
{
    int ans=0,a1,b1,x;
    pair<int,int> p;
    scanf("%d",&n);
    scanf("%s",s1);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    scanf("%s",s2);
    for (int i=1;i<=n;i++) scanf("%d",&b[i]);
    if (s1[0]=='C'&&s2[0]=='C')
    {
        for (int i=1;i<=n;i++)
            if (a[i]!=b[i])
            {
                printf("-1\n");
                return 0;
            }
        printf("0\n");
        return 0;
    }
    for (int i=1;i<=100000;i++) fa[i]=i;
    for (int i=1;i<=n;i++)
        if (find(a[i])!=find(b[i]))
        {
            ans++;
            fa[fa[a[i]]]=fa[b[i]];
        }
    if (s1[0]==s2[0])
    {
        printf("%d\n",ans);
        return 0;
    }
    for (int i=1;i<=n;i++)
        if (a[i]!=b[i])
        {
            ord[++v]=a[i];
            ord[++v]=b[i];
        }
    sort(ord+1,ord+v);
    v=unique(ord+1,ord+v+1)-ord-1;
    for (int i=1;i<=v;i++) fa[i]=i;
    for (int i=1;i<=n;i++)
        if (a[i]!=b[i])
        {
            a1=lower_bound(ord+1,ord+v+1,a[i])-ord;
            b1=lower_bound(ord+1,ord+v+1,b[i])-ord;
            to[a1].push_back(b1);
            in[b1]++;
            fa[find(a1)]=find(b1);
        }
    for (int i=1;i<=v;i++) bel[find(i)].push_back(i);
    for (int i=1;i<=v;i++)
        if (fa[i]==i)
        {
            hd=1,tl=0;
            for (vector<int>::iterator it=bel[i].begin();it!=bel[i].end();it++)
                if (!in[*it]) que[++tl]=(*it);
            while (hd<=tl)
            {
                x=que[hd++];
                for (vector<int>::iterator it=to[x].begin();it!=to[x].end();it++)
                {
                    in[*it]--;
                    if (!in[*it]) que[++tl]=*it;
                }
            }
            if (tl<bel[i].size()) ans++;
        }
    printf("%d\n",ans);
}

猜你喜欢

转载自blog.csdn.net/sdfzyhx/article/details/81006098
今日推荐