UVALive-5013 Similarity(二分图最大权匹配)

xiaoxiao2021-02-28  126

题意:

给出一正确字符序列,然后再给出相同长度的字符序列,第二个序列需要确定给定字符与正确序列相对应。求最大相似比率(正确的个数/总个数)。

思路:

很容易直接想到二分图的最大权匹配,将两个相对应的字符建边,并以其重复个数为权值,然后跑一遍KM就可以了。

代码:

#include <algorithm> #include <iostream> #include <string.h> #include <string> #include <cstdio> #include <map> using namespace std; const int maxn = 10005; const int inf = 0x3f3f3f3f; char s[maxn*2]; map<int, int> mp; int T, N, K, M; int num1[maxn], num2[maxn]; int cnt; int weight[30][30]; int match[30]; int lx[30], ly[30]; int visx[30], visy[30]; int slack[30]; int dfs(int cur) { visx[cur] = 1; for(int i = 1; i <= K; ++i) { if(visy[i]) continue; int gap = lx[cur]+ly[i]-weight[cur][i]; if(gap == 0) { visy[i] = 1; if(match[i] == -1 || dfs(match[i])) { match[i] = cur; return 1; } } else slack[i] = min(slack[i], gap); } return 0; } int KM() { memset(match, -1, sizeof match); memset(ly, 0, sizeof ly); for(int i = 1; i <= cnt; ++i) { lx[i] = weight[i][1]; for(int j = 2; j <= K; ++j) lx[i] = max(lx[i], weight[i][j]); } for(int i = 1; i <= cnt; ++i) { memset(slack, 0x3f, sizeof slack); while(1) { memset(visx, 0, sizeof visx); memset(visy, 0, sizeof visy); if(dfs(i)) break; int mins = inf; for(int j = 1; j <= K; ++j) if(!visy[j]) mins = min(mins, slack[j]); for(int j = 1; j <= cnt; ++j) if(visx[j]) lx[j] -= mins; for(int j = 1; j <= K; ++j) if(visy[j]) ly[j] += mins; } } int ans = 0; for(int i = 1; i <= K; ++i) if(match[i] != -1) ans += weight[match[i]][i]; return ans; } int main() { scanf("%d", &T); while(T--) { scanf("%d %d %d", &N, &K, &M); getchar(); gets(s); cnt = 0; mp.clear(); for(int i = 0; i < N; ++i) if(mp.count(s[i*2])) num1[i+1] = mp[s[i*2]]; else { mp[s[i*2]] = ++cnt; num1[i+1] = cnt; } for(int _ = 1; _ <= M; ++_) { memset(weight, 0, sizeof weight); cnt = 0; mp.clear(); gets(s); for(int i = 0; i < N; ++i) if(mp.count(s[i*2])) num2[i+1] = mp[s[i*2]]; else { mp[s[i*2]] = ++cnt; num2[i+1] = cnt; } for(int i = 1; i <= N; ++i) //令cnt为A部个数,防止死循环 ++weight[num2[i]][num1[i]]; printf("%.4f\n", KM()*1.0/N); } } return 0; }

继续加油~

转载请注明原文地址: https://www.6miu.com/read-39616.html

最新回复(0)