[HDOJ3718]Similarity(KM算法,二分图最大匹配)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3718

题意:有一堆答题情况和正确答案,问每一个答题情况的正确率最大是多少。

给每一对答案和答题情况的字母做映射,每次映射权值+1,这样会构造出一个二分图。在这个二分图上做最大匹配结果除以题目数量就是正确率。

 #include <bits/stdc++.h>
using namespace std; const int maxm = ;
const int maxn = ;
const int inf = 0x3f3f3f3f;
int n, m, k;
int nx,ny;
int G[maxn][maxn];
int linker[maxn],lx[maxn],ly[maxn];
int slack[maxn];
bool visx[maxn],visy[maxn];
char ans[maxm];
char stu[maxm]; bool dfs(int x) {
visx[x] = true;
for(int y = ; y < ny; y++) {
if(visy[y])continue;
int tmp = lx[x] + ly[y] - G[x][y];
if(tmp == ) {
visy[y] = true;
if(linker[y] == - || dfs(linker[y])) {
linker[y] = x;
return true;
}
}
else if(slack[y] > tmp)
slack[y] = tmp;
}
return false;
}
int km() {
memset(linker,-,sizeof(linker));
memset(ly,,sizeof(ly));
for(int i = ;i < nx;i++) {
lx[i] = -inf;
for(int j = ;j < ny;j++)
if(G[i][j] > lx[i])
lx[i] = G[i][j];
}
for(int x = ;x < nx;x++) {
for(int i = ;i < ny;i++)
slack[i] = inf;
while(true) {
memset(visx,false,sizeof(visx));
memset(visy,false,sizeof(visy));
if(dfs(x))break;
int d = inf;
for(int i = ;i < ny;i++)
if(!visy[i] && d > slack[i])
d = slack[i];
for(int i = ;i < nx;i++)
if(visx[i])
lx[i] -= d;
for(int i = ;i < ny;i++) {
if(visy[i])ly[i] += d;
else slack[i] -= d;
}
}
}
int res = ;
for(int i = ;i < ny;i++)
if(linker[i] != -)
res += G[linker[i]][i];
return res;
} int main() {
// freopen("in", "r", stdin);
int T;
scanf("%d", &T);
nx = ny = ;
while(T--) {
scanf("%d%d%d",&n,&k,&m);
for(int i = ; i < n; i++) {
cin >> ans[i];
}
for(int _ = ; _ < m; _++) {
for(int i = ; i < n; i++) {
cin >> stu[i];
}
memset(G, , sizeof(G));
for(int i = ; i < n; i++) {
G[stu[i]-'A'][ans[i]-'A']++;
}
printf("%.4lf\n", (double)km()/(double)n);
}
} return ;
}
上一篇:OC语言(六)


下一篇:最新版ssh hibernate spring struts2环境搭建