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

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

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

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

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxm = 10100;
 5 const int maxn = 80;
 6 const int inf = 0x3f3f3f3f;
 7 int n, m, k;
 8 int nx,ny;
 9 int G[maxn][maxn];
10 int linker[maxn],lx[maxn],ly[maxn];
11 int slack[maxn];
12 bool visx[maxn],visy[maxn];
13 char ans[maxm];
14 char stu[maxm];
15 
16 bool dfs(int x) {
17   visx[x] = true;
18   for(int y = 0; y < ny; y++) {
19     if(visy[y])continue;
20     int tmp = lx[x] + ly[y] - G[x][y];
21     if(tmp == 0) {
22       visy[y] = true;
23       if(linker[y] == -1 || dfs(linker[y])) {
24         linker[y] = x;
25         return true;
26       }
27     }
28     else if(slack[y] > tmp)
29       slack[y] = tmp;
30   }
31   return false;
32 }
33 int km() {
34   memset(linker,-1,sizeof(linker));
35   memset(ly,0,sizeof(ly));
36   for(int i = 0;i < nx;i++) {
37     lx[i] = -inf;
38     for(int j = 0;j < ny;j++)
39       if(G[i][j] > lx[i])
40         lx[i] = G[i][j];
41   }
42   for(int x = 0;x < nx;x++) {
43     for(int i = 0;i < ny;i++)
44       slack[i] = inf;
45     while(true) {
46       memset(visx,false,sizeof(visx));
47       memset(visy,false,sizeof(visy));
48       if(dfs(x))break;
49       int d = inf;
50       for(int i = 0;i < ny;i++)
51         if(!visy[i] && d > slack[i])
52           d = slack[i];
53       for(int i = 0;i < nx;i++)
54         if(visx[i])
55           lx[i] -= d;
56       for(int i = 0;i < ny;i++) {
57         if(visy[i])ly[i] += d;
58         else slack[i] -= d;
59       }
60     }
61   }
62   int res = 0;
63   for(int i = 0;i < ny;i++)
64     if(linker[i] != -1)
65       res += G[linker[i]][i];
66   return res;
67 }
68 
69 int main() {
70   // freopen("in", "r", stdin);
71   int T;
72   scanf("%d", &T);
73   nx = ny = 26;
74   while(T--) {
75   scanf("%d%d%d",&n,&k,&m);
76   for(int i = 0; i < n; i++) {
77     cin >> ans[i];
78   }
79   for(int _ = 0; _ < m; _++) {
80     for(int i = 0; i < n; i++) {
81     cin >> stu[i];
82     }
83     memset(G, 0, sizeof(G));
84     for(int i = 0; i < n; i++) {
85     G[stu[i]-'A'][ans[i]-'A']++;
86     }
87     printf("%.4lf
", (double)km()/(double)n);
88   }
89   }
90 
91   return 0;
92 }
原文地址:https://www.cnblogs.com/kirai/p/5959515.html