HDU_3718

我们首先要把字符串中的字符转化成意义相同的[0,k-1]之间的数,然后顺序扫描一遍数组,就可以得到两组数之间的各种匹配的最大值,这样就完成了建图。

之后运用KM算法求最优匹配即可。

#include<stdio.h>
#include<string.h>
#define MAXD 30
#define MAXN 10010
#define INF 1000000000
char a[MAXN][5], b[MAXN][5];
int visa[MAXN], visb[MAXN], x[MAXN], y[MAXN];
int G[MAXD][MAXD], yM[MAXD], N, K, M;
int A[MAXD], B[MAXD], slack;
int visx[MAXD], visy[MAXD];
void init()
{
int i, j, k;
for(i = 0; i < N; i ++)
scanf("%s", a[i]);
memset(visa, 0, sizeof(visa));
k = 0;
for(i = 0; i < N; i ++)
if(!visa[i])
{
for(j = i; j < N; j ++)
if(a[j][0] == a[i][0])
{
visa[j] = 1;
x[j] = k;
}
k ++;
}
}
void initM()
{
int i, j, k;
for(i = 0; i < N; i ++)
scanf("%s", b[i]);
memset(visb, 0, sizeof(visb));
k = 0;
for(i = 0; i < N; i ++)
if(!visb[i])
{
for(j = i; j < N ; j ++)
if(b[j][0] == b[i][0])
{
visb[j] = 1;
y[j] = k;
}
k ++;
}
memset(G, 0, sizeof(G));
for(i = 0; i < N; i ++)
G[x[i]][y[i]] ++;
}
int searchpath(int u)
{
int v, temp;
visx[u] = 1;
for(v = 0; v < K; v ++)
if(!visy[v])
{
temp = A[u] + B[v] - G[u][v];
if(temp == 0)
{
visy[v] = 1;
if(yM[v] == -1 || searchpath(yM[v]))
{
yM[v] = u;
return 1;
}
}
else if(temp < slack)
slack = temp;
}
return 0;
}
void KM()
{
int i, j, u;
for(i = 0; i < K; i ++)
{
A[i] = 0;
for(j = 0; j < K; j ++)
if(G[i][j] > A[i])
A[i] = G[i][j];
}
memset(B, 0, sizeof(B));
memset(yM, -1, sizeof(yM));
for(u = 0; u < K; u ++)
for(;;)
{
memset(visx, 0, sizeof(visx));
memset(visy, 0, sizeof(visy));
slack = INF;
if(searchpath(u))
break;
for(i = 0; i < K; i ++)
{
if(visx[i])
A[i] -= slack;
if(visy[i])
B[i] += slack;
}
}
}
void printresult()
{
int i, res =0;
for(i = 0 ; i < K; i ++)
res += G[yM[i]][i];
printf("%.4f\n", (double)res / N);
}
int main()
{
int i, T;
scanf("%d", &T);
while(T --)
{
scanf("%d%d%d", &N, &K, &M);
init();
for(i = 0; i < M; i ++)
{
initM();
KM();
printresult();
}
}
return 0;
}


posted on 2011-10-05 15:29  Staginner  阅读(235)  评论(0编辑  收藏  举报