Codeforces - Deciphering

题目链接:Codeforces - Deciphering


我们其实可以看成是字母直接的匹配,然后求一个最大权值的匹配。

怎么求对应的权值呢?显然我们只需要知道某个字母转化为另一个字母的价值,直接遍历一遍即可。

最后还需要输出对应的匹配,就是link数组,注意link[i]是匹配 i 的点,而不是 i 匹配的link[i],注意。


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1e3+10,M=1e6+10;
int n,k,res[N];	char a[M<<1],b[M<<1]; map<int,int> mp,rmp;
struct KM{
	int w[N][N],lx[N],ly[N],visy[N],slack[N],pre[N],link[N];
	int bfs(int k){
		int x,y=0,yy=0,delta;	memset(pre,0,sizeof pre);
		for(int i=1;i<=n;i++)	slack[i]=inf;	link[y]=k;
		while(1){
			x=link[y],delta=inf,visy[y]=1;
			for(int i=1;i<=n;i++){
				if(!visy[i]){
					if(slack[i]>lx[x]+ly[i]-w[x][i])
						slack[i]=lx[x]+ly[i]-w[x][i],pre[i]=y;
					if(slack[i]<delta) delta=slack[i],yy=i;
				}
			}
			for(int i=0;i<=n;i++){
				if(visy[i])	lx[link[i]]-=delta,ly[i]+=delta;
				else	slack[i]-=delta;
			}
			y=yy;	if(link[y]==-1)	break;
		}
		while(y)	link[y]=link[pre[y]],y=pre[y];
	}
	int calc(){
		memset(link,-1,sizeof link);	int res=0;
		for(int i=1;i<=n;i++)	memset(visy,0,sizeof visy),bfs(i);
		for(int i=1;i<=n;i++)	if(link[i])	res+=w[link[i]][i];
		return res;
	}
}s;
signed main(){
	cin>>n>>k;	scanf("%s %s",a+1,b+1);
	for(int i=1;i<=k;i++){
		if('a'+i-1<='z')	mp['a'+i-1]=i,rmp[i]='a'+i-1;
		else	mp['a'+i-2-'z'+'A']=i,rmp[i]='a'+i-2-'z'+'A';
	}
	for(int i=1;i<=n;i++)	s.w[mp[a[i]]][mp[b[i]]]++;	n=k;
	cout<<s.calc()<<endl;
	for(int i=1;i<=n;i++)	res[s.link[i]]=i;
	for(int i=1;i<=n;i++)	printf("%c",rmp[res[i]]);
	return 0;
}
发布了725 篇原创文章 · 获赞 244 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/104729813