这题就是一道KM算法的模版题,下午做比赛的时候两个模版都是TLE,好不科学,比赛结束后去杭电交就成WA了,更不科学……后来发现是建图的时候写挫了T_T,要不比赛的时候就能多出一题了,还有一道匹配题也没敢写,一会就去写一下。话说根本不知道KM的实现啊,只知道抄模版,感觉自己好挫啊……
#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;
#define MAX 205
#define INF 9999999
int n,match[MAX];
bool sx[MAX],sy[MAX];
char str[MAX][1005];
int lx[MAX],ly[MAX],map[MAX][MAX];
bool path(int u)
{
sx[u]=true;
for(int v=0;v<n;v++)
if(!sy[v]&&lx[u]+ly[v]==map[u][v])
{
sy[v]=true;
if(match[v]==-1||path(match[v]))
{
match[v]=u;
return true;
}
}
return false;
}
int KM(bool truth)//可以不用更改地处理最小或最大权匹配
{
int i,j;
if(!truth)
{
for(i=0;i<n;i++)
for(j=0;j<n;j++)
map[i][j]=-map[i][j];
}
for(i=0;i<n;i++)
{
lx[i]=-INF;
ly[i]=0;
for(j=0;j<n;j++)
if(lx[i]<map[i][j])
lx[i]=map[i][j];
}
memset(match,-1,sizeof(match));
for(int u=0;u<n;u++)
while(1)
{
memset(sx,0,sizeof(sx));
memset(sy,0,sizeof(sy));
if(path(u)) break;
int dmin=INF;
for(i=0;i<n;i++)
if(sx[i])
for(j=0;j<n;j++)
if(!sy[j])
dmin=min(lx[i]+ly[j]-map[i][j],dmin);
for(i=0;i<n;i++)
{
if(sx[i])
lx[i]-=dmin;
if(sy[i])
ly[i]+=dmin;
}
}
int sum=0;
for(j=0;j<n;j++)
sum+=map[match[j]][j];
if(!truth)
{
sum=-sum;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
map[i][j]=-map[i][j];
}
return sum;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
memset(str,0,sizeof(str));
for(int i=0;i<n;i++)
scanf("%s",&str[i]);
for(int i=0;i<n;i++) //建图
{
for(int j=0;j<n;j++)
{
if(i==j)
{
map[i][j]=0;
continue;
}
int temp=0;
int len1=strlen(str[i]),len2=strlen(str[j]);
int len=min(len1,len2);
for(int k=0;k<len;k++)
{
if(str[i][k]==str[j][len2-k-1])
{
temp++;
}
else break; //这里忘记break了
}
map[i][j]=temp; //map[i][j]!=map[j][i],之前还以为他们是相等的……
}
}
int ans=KM(1);
printf("%d\n",ans);
}
}