#include <stdio.h>
#include <string.h>
#include <vector>
#include <iostream>
using namespace std;
#define _clr(x) memset(x, -1, sizeof(int)*MAXN)
#define MAXN 40
#define inf 10000000
#define FOR(i,s,e) for (int i=(s);(i)<(e);i++)
int sign_a[35];
int sign_b[35];
int mat[40][40];
int match1[40];
int match2[40];
int km(int m, int n, int mat[][MAXN], int* match1, int* match2)
{
int s[MAXN];
int t[MAXN];
int l1[MAXN];
int l2[MAXN];
int p;
int q;
int ret = 0;
int i;
int j;
int k;
for (i=0; i<m; i++)
{
for (l1[i]=-inf,j=0; j<n; j++)
l1[i] = mat[i][j] > l1[i] ? mat[i][j]:l1[i];
if (l1[i] == -inf) return -1;
}
for (i=0; i<n; l2[i++] = 0);
for (_clr(match1), _clr(match2), i=0; i<m; i++)
{
for ((_clr(t)), s[p=q=0]=i; p<=q && match1[i] < 0; p++)
for (k=s[p],j=0; j < n && match1[i] < 0; j++)
if (l1[k] + l2[j] == mat[k][j] && t[j] < 0)
{
s[++q] = match2[j],t[j] = k;
if (s[q] < 0)
for (p = j; p>=0; j=p)
match2[j] = k =t[j], p = match1[k], match1[k] = j;
}
if (match1[i] < 0)
{
for (i--,p=inf,k=0; k<=q; k++)
for (j=0; j<n; j++)
if (t[j] < 0 && l1[s[k]] + l2[j] - mat[s[k]][j] < p)
p = l1[s[k]] + l2[j] - mat[s[k]][j];
for (j=0; j<n; l2[j]+=t[j]<0?0:p,j++);
for (k = 0; k <= q; l1[s[k++]]-=p);
}
}
for (i=0; i<m; i++)
{
if (match1[i] < 0) return -1;
if (mat[i][match1[i]] <= -inf) return -1;
ret+=mat[i][match1[i]];
}
return ret;
}
char s[20010];
char tea[20010];
char stu[20010];
int main()
{
int num;
int t,n,m,k;
//freopen("in.txt","r",stdin);
scanf("%d",&t);
while (t--)
{
scanf("%d%d%d",&n,&k,&m);
getchar();
gets(s);
num = 0;
for (int i=0; s[i] ; i++)
if (s[i]!=' ' )
tea[num++]=s[i];
tea[num]='\0';
memset(sign_a,0,sizeof(sign_a));
num = 1;
for (int i=0; tea[i]; i++)
if (tea[i]>='A' && tea[i]<='Z' && sign_a[tea[i]-'A'] == 0)
sign_a[tea[i]-'A']=num++;
FOR(i,0,m)
{
memset(sign_b,0,sizeof(sign_b));
memset(mat,0,sizeof(mat));
gets(s);
num = 0;
for (int i=0; s[i]; i++)
if (s[i]!=' ')
stu[num++]=s[i];
stu[num]='\0';
num =1;
for (int i=0; stu[i]; i++)
if (stu[i]>='A' && stu[i]<='Z' && sign_b[stu[i]-'A'] == 0)
sign_b[stu[i]-'A']=num++;
for (int i=0; tea[i]; i++)
mat[sign_a[tea[i]-'A']-1][sign_b[stu[i]-'A']-1]++;
printf("%.4lf\n",km(k,k,mat,match1,match2)*1.0/n );
}
}
return 0;
}
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4109
模拟+KM。表示只会写模拟。。。手贱把'\0' 写成' \n ' 而导致RE。