Similarity
题目链接:Click Here~
题目分析:
给你N个字符[A,Z]每个字符代表一种类型,而字符只是个代号,并没有多大的作用。就是题目中的这句话:
So the representations {P,P,O,P,O,O,Q,Q,Q,Q} and {E,E,F,E,F,F,W,W,W,W} are equivalent to the original mapping sequence. However, the representations {A,A,A,A,B,B,C,C,C,C} and
{D,D,D,D,D,D,G,G,G,G} are not equivalent.表示很难解释~,还是自己看题目吧。我说一下题目要我们求的是什么吧,题目要求你求出每个类型跟答案可以匹配的最大数是多少。然后,最大数除以长度就是答案了。
算法分析:
可以看出这是一个匹配问题,而且是最大权匹配,所以直接套用模板就好了。别的就是建图的时候的问题了,可能要另外处理一下。
建模分析:
对每个字符标记为一种类型,如果同属于第i个的字符这把他们连一条线。
例如,
A A B A B B C C C C(Answer String)
F F E F E E D D D D
X X X Y Y Y Y Z Z Z
建图为:
(1,1) (1,1) (2,2) (1,1) (2,2) (2,2) (3,3) (3,3) (3,3) (3,3) ----->10/10
(1,1) (1,1) (2,1) (1,2) (2,2) (2,2) (3,2) (3,3) (3,3) (3,3) ----->7/10
#include <iostream> #include <algorithm> #include <vector> #include <queue> #include <cstdio> #include <cstring> using namespace std; const int INF = ~0U >> 1; const int MAXN = 1e4 + 5; int n,m,k; int W[30][30],ans[MAXN],hash[30]; int slack,Lx[30],Ly[30],Link[30]; bool S[30],T[30]; bool Match(int i) { S[i] = true; for(int j = 1;j <= k;++j)if(!T[j]){ int tmp = Lx[i]+Ly[j] - W[i][j]; if(tmp==0){ T[j] = true; if(Link[j]==-1||Match(Link[j])){ Link[j] = i; return true; } } else if(tmp < slack) slack = tmp; } return false; } void Update(int d) { for(int i = 1;i <= k;++i){ if(S[i]) Lx[i] -= d; if(T[i]) Ly[i] += d; } } bool EK() { for(int i = 1;i <= k;++i){ Link[i] = -1; Lx[i] = Ly[i] = 0; for(int j = 1;j <= k;++j) Lx[i] = max(Lx[i],W[i][j]); } slack = INF; for(int i = 1;i <= k;++i){ for(;;){ memset(S,false,sizeof(S)); memset(T,false,sizeof(T)); if(Match(i)) break; if(slack == INF) return false; Update(slack); } } return true; } int GetAns() { int sum = 0; for(int i = 1;i <= k;++i) if(Link[i]!=-1){ sum += W[Link[i]][i]; } return sum; } int main() { // freopen("Input.txt","r",stdin); // freopen("Out.txt","w",stdout); int T; scanf("%d",&T); while(T--) { char str[2]; int cnt = 1; memset(ans,0,sizeof(ans)); memset(hash,0,sizeof(hash)); scanf("%d%d%d",&n,&k,&m); for(int i = 0;i < n;++i){ scanf("%s",str); if(!hash[str[0]-‘A‘]) hash[str[0]-‘A‘] = cnt++; ans[i] = hash[str[0]-‘A‘]; } for(int i = 0;i < m;++i){ cnt = 1; memset(W,0,sizeof(W)); memset(hash,0,sizeof(hash)); for(int j = 0;j < n;++j){ scanf("%s",str); if(!hash[str[0]-‘A‘]) hash[str[0]-‘A‘] = cnt++; W[ans[j]][hash[str[0]-‘A‘]]++; } EK(); int sum = GetAns(); printf("%.4lf\n",(sum*1.0)/(n*1.0)); } } return 0; }
Similarity (2010成都赛区,KM),布布扣,bubuko.com
原文:http://blog.csdn.net/zhongshijunacm/article/details/23607107