一个二分图最大匹配的题;
匈牙利算法不熟;
建了个模,用最小费用最大流解决了
#include <iostream>
#include <cstring>
#define INF 9999999
#include <cstdio>
#include <queue>
#include <vector>
#include<algorithm>
using namespace std;
#define maxn 6100 struct edge
{
int from,to,cap,flow,cost;
};
struct MCMF
{
int n,m,s,t;
vector<edge>edges;
vector<int>G[maxn];
int inq[maxn];
int d[maxn];
int p[maxn];
int a[maxn];
void init(int n)
{
this->n=n;
for(int i=; i<n; i++)
G[i].clear();
edges.clear();
}
void addedge(int from,int to,int cap,int cost)
{
edges.push_back((edge){from,to,cap,,cost});
edges.push_back((edge){to,from,,,-cost});
m=edges.size();
G[from].push_back(m-);
G[to].push_back(m-);
} bool bellman(int s,int t,int &flow,int &cost)
{
for(int i=; i<n; i++)d[i]=INF;
memset(inq,,sizeof(inq));
d[s]=;
inq[s]=;
p[s]=;
a[s]=INF; queue<int>Q;
Q.push(s);
while(!Q.empty())
{
int u = Q.front();
Q.pop();
inq[u] = ;
for(int i = ; i < G[u].size(); i++)
{
edge& e = edges[G[u][i]];
if(e.cap > e.flow && d[e.to] > d[u] + e.cost)
{
d[e.to] = d[u] + e.cost;
p[e.to] = G[u][i];
a[e.to] = min(a[u], e.cap - e.flow);
if(!inq[e.to])
{
Q.push(e.to);
inq[e.to] = ;
}
}
}
}
if(d[t] == INF) return false;
flow += a[t];
cost += d[t]*a[t];
int u = t;
while(u != s)
{
edges[p[u]].flow += a[t];
edges[p[u]^].flow -= a[t];
u = edges[p[u]].from;
}
return true;
}
int Mincost(int s, int t)
{
int flow = , cost = ;
while(bellman(s, t, flow, cost));
return cost;
}
};
int n;
int k,m;
char s2[],s1[];
int cur[][];
int tot[];
void first_solve()
{
memset(cur,,sizeof(cur));
memset(tot,,sizeof(tot));
for(int i=; i<=n; i++)
{
int k1=s1[i]-'A'+;
int k2=s2[i]-'A'+;
tot[k1]++;
cur[k1][k2]++;
}
}
MCMF solve;
int main()
{
int t;
int st=;
int final=;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&k,&m);
for(int i=; i<=n; i++)
{
char s[];
scanf("%s",s);
s1[i]=s[];
}
for(int d=; d<=m; d++)
{
solve.init(final+);
for(int j=; j<=n; j++)
{
char s[];
scanf("%s",s);
s2[j]=s[];
}
first_solve();
for(int i=; i<=; i++)
solve.addedge(st,i,,);
for(int i=; i<=; i++)
{
for(int j=; j<=; j++)
{
int cnt=+j;
if (cur[i][j])
solve.addedge(i,cnt,,tot[i]-cur[i][j]);
else solve.addedge(i,cnt,,tot[i]);
}
}
for(int i=;i<=;i++)solve.addedge(i+,final,,);
int ans=n-solve.Mincost(st,final);
printf("%.4lf\n",(double)ans/(double)n);
}
}
return ;
}