【2018 計蒜之道 複賽】計蒜客 貝殼找房魔法師顧問
阿新 • • 發佈:2019-02-05
需要注意的問題是修改是可以傳遞的,也就是如果能改成,能改成,那麼就能改成。
如果兩個串都是可修改的比較簡單,只需要用並查集維護可以相互修改的元素就可以了。
如果只有一個串是可修改的,相當於邊是有向邊,不難證明如下結論:對每個連通塊,如果它有環,那麼需要多加一條邊。否則和無向圖是一樣的。
#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);
}