P9013 [USACO23JAN] Find and Replace S

洛谷

你说得对,但是图论是初学者的弱点。

首先每个字母只能对应一个字母,这应该没有异议吧。

通过对示例进行模拟,我们不难发现,这道题的难点在于:环该如何处理。

情况比较复杂需要仔细分析,但是由于每个点出度均为 \(1\) ,所以分析起来并不难。

假设每一个字母都是一个点建图,分两种情况讨论。

第一种情况,如果字母没有全部选择完。

如果这部分形成树状,那么每个点需要改变一次,除非这个点连接的是自己。

所用次数为所需改变的树上节点的个数,若连接自己则不用加一。

例如:

abc
bbc

如果形成环状,那么每一个环中都需要有一个点先变成某一个不在图中,其他点形成树状,将这个树处理后,将那个点变为需要变的点即可。

由于如果你本来就不需要变,出度为 \(1\) 则不可能和其他点成为环,所以不考虑有自连的情况。

那么除了环内的点加一以外长度额外加一。

例如:

ABC
BCA

最特殊的形式,叫基环树,就是一个环上插一颗树,大概就是这样:

ABCDEF
BCAADE

那么此时就有一个很好的处理方式了。

\(C\) 变为 \(D\) ,把环拆成树,之后再将新树 \(ABC\) 解决了,再把 \(D\) 变为 \(A\) ,最后解决掉树 \(DEF\) 即可。

那么就和树所耗的次数相同,都是每有一个点就改变一次。

而这种同样没有自连情况。

那么我们不难发现在此情况下,大部分都用一次,而唯独在树上自恋时减一和有普通环时额外加一。

那么还有第二种情况:所有字母都用完了。

需要变成其他字母的只有环,所以环的处理会受到影响。

如果全都是环,那么肯定不行了。

但是如果产生了基环树或者有自连的树(非单个点),那么就会有空位产生,就能够解决。

这样就讨论完了全部情况,使用一个并查集查找环再具体分析处理即可。

代码:

#include<bits/stdc++.h>
using namespace std;
char s[100005];
int T,a[100005],b[100005],c[100005],t[100005],fa[100005];
bool vis[100005];
int uid(char c){
	if(c<='Z')return c-'A'+1;
	else return c-'a'+27;
}
int find(int x){
	if(x==fa[x])return x;
	return fa[x]=find(fa[x]);
}
void merge(int x,int y){
	x=find(x),y=find(y);
	if(x==y)return;
	fa[x]=y;
}
signed main(){
	cin>>T;
	while(T--){
		memset(c,0,sizeof(c));
		memset(t,0,sizeof(t));
		memset(vis,0,sizeof(vis));
		for(int i=1;i<=52;i++)fa[i]=i;
		cin>>s+1;
		int len=strlen(s+1);
		for(int i=1;i<=len;i++)a[i]=uid(s[i]);
		cin>>s+1;
		for(int i=1;i<=len;i++)b[i]=uid(s[i]);
		bool f=0;
		int cnt=0;
		for(int i=1;i<=len;i++){
			if(!c[a[i]])c[a[i]]=b[i],t[b[i]]++,cnt++;
			else if(c[a[i]]!=b[i])f=1;
		}
		if(f){
			puts("-1");
			continue;
		}
		for(int i=1;i<=52;i++)if(c[i])merge(i,c[i]);
		bool fl=0;
		int ans=0;
		for(int i=1;i<=52;i++)if(c[i]&&t[c[i]]>1)fl=1,vis[find(i)]=1;
		for(int i=1;i<=52;i++){
			if(!c[i])continue;
			if(find(i)!=i)ans++;
			else {
				if(i==c[i])continue;
				if(vis[i])ans++;
				else if(!fl&&cnt==52)f=1;
				else ans+=2;
			}
		}
		if(f){
			puts("-1");
			continue;
		}
		cout<<ans<<endl;
	}
	return 0;
} 
posted @ 2025-10-31 09:15  huhangqi  阅读(7)  评论(0)    收藏  举报
/*
*/