For example, there are 3 cards, whose strings are S1="ab", S2="bcc", S3="ccb". There are 6 possible sticking:
1. S1->S2, S2->S3, S3->S1, the score is 1+3+0 = 4
2. S1->S2, S2->S1, S3->S3, the score is 1+0+0 = 1
3. S1->S3, S3->S1, S2->S2, the score is 0+0+0 = 0
4. S1->S3, S3->S2, S2->S1, the score is 0+3+0 = 3
5. S1->S1, S2->S2, S3->S3, the score is 0+0+0 = 0
6. S1->S1, S2->S3, S3->S2, the score is 0+3+3 = 6
So the best score is 6.
Given the information of all the cards, please help Jimmy find the best possible score.
3 ab bcc ccb 1 abcd
6 0
//
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
const int N=210;
const int inf=(1<<28);
//w是完全图,若i->j没有路,则w[i][j]=inf;
//若有多条路,则取最小路
int n,m;//点数1->n,边数
int match[N],lack,w[N][N],lx[N],ly[N];;
bool visx[N],visy[N];
bool dfs(int x){
visx[x]=true;
for(int y=1; y<=n; y++){
if(visy[y]) continue;
int t=lx[x]+ly[y]-w[x][y];
if(t==0){
visy[y]=true;
if(match[y]==-1||dfs(match[y])){
match[y]=x;
return true;
}
}
else if(lack>t) lack=t;
}
return false;
}
int KM(){
int i,j;
for(i=0;i<=n;i++)lx[i]=0;
for(i=0;i<=n;i++)ly[i]=0;
memset(match,-1,sizeof(match));
for(i=1; i<=n; i++)for( j=1; j<=n; j++)if(w[i][j]>lx[i]) lx[i]=w[i][j];
for(int x=1; x<=n; x++){
while(1){
memset(visx,0,sizeof(visx));
memset(visy,0,sizeof(visy));
lack=inf;
if(dfs(x)) break;
for(i=1; i<=n; i++){
if(visx[i]) lx[i]-=lack;
if(visy[i]) ly[i]+=lack;
}
}
}
int total=0;
for(i=1;i<=n;i++)
{
total+=w[match[i]][i];
}
return total;
}
char s[1010][1010];
int len[1010];
int main()
{
int i,j;
//freopen("c.txt","r",stdin);
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++)
{
scanf("%s",&s[i]);
len[i]=strlen(s[i]);
}
memset(w,0,sizeof(w));
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(i==j)w[i][j]=0;
else
{
int x=len[i]-1;
int y=0;
int tmp=0;
while(x>=0&&y<len[j])
{
if(s[i][x]==s[j][y])
{
tmp++;
x--;
y++;
}
else break;
}
w[i][j]=tmp;
}
}
}
printf("%d\n",KM());
}
return 0;
}