题目大意: 两个字符串之间可以计算出费用,然后用 KM算法 最大化这个费用和。。。
//KM算法求最大匹配
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define Maxn 210
#define INF 0x3f3f3f3f
int map[Maxn][Maxn],match[Maxn],slack[Maxn],lx[Maxn],ly[Maxn];
bool visx[Maxn],visy[Maxn];
int n,m;
bool dfs(int i){
visx[i]=true;
for (int j=1;j<=m;j++){
if (visy[j]) continue;
int tmp=lx[i]+ly[j]-map[i][j];
if (tmp==0){
visy[j]=true;
if (match[j]==-1|| dfs(match[j])){
match[j]=i;
return true;
}
}
else
if (tmp<slack[j]) slack[j]=tmp;
}
return false;
}
int KM(){
memset(match,-1,sizeof(match));
memset(ly,0,sizeof(ly));
for (int i=1;i<=n;i++){
lx[i]=-INF;
for (int j=1;j<=m;j++)
lx[i]=max(lx[i],map[i][j]);
}
for (int k=1;k<=n;k++){
for (int i=1;i<=m;i++) slack[i]=INF;
while (1){
memset(visx,false,sizeof(visx));
memset(visy,false,sizeof(visy));
if (dfs(k)) break;
int dx=INF;
for (int i=1;i<=m;i++)
if (!visy[i]&&slack[i]<dx) dx=slack[i];
for (int i=1;i<=n;i++)
if (visx[i]) lx[i]-=dx;
for (int i=1;i<=m;i++)
if (visy[i]) ly[i]+=dx;
else slack[i]-=dx;
}
}
int ret=0;
for (int i=1;i<=m;i++){
ret+=map[match[i]][i];
}
return ret;
}
char s1[Maxn][1050],s2[Maxn][1050];
void reverse(char des[],char src[]){
int len=strlen(src);
for (int i=0;i<len;i++){
des[i]=src[len-1-i];
}
}
int main(){
while (~scanf("%d",&n)){
m=n;
for (int i=1;i<=n;i++){
scanf("%s",s1[i]);
reverse(s2[i],s1[i]);
}
memset(map,0,sizeof(map));
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++)if (i!=j){
int sum=0;
int len=min(strlen(s1[i]),strlen(s2[j]));
for (int k=0;k<len;k++){
if (s1[i][k]==s2[j][k]) sum++;
else break;
}
map[i][j]=sum;
}
}
int ans=KM();
printf("%d\n",ans);
}
return 0;
}