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