hdu 3718 KM最优匹配
建图过程,上面一行字母与下面一行一一对应连边,再利用KM求一个最优匹配即可
#include<stdio.h> #include<string.h> #include<string> #include<vector> #include<stdlib.h> using namespace std; #define MIN(a,b) a<b?a:b #define INF 999999 #define MAX 50 int match[MAX]; bool sx[MAX],sy[MAX]; int lx[MAX],ly[MAX],map[MAX][MAX]; bool path(int u) { sx[u]=true; for(int v=0;v<26;v++) if(!sy[v]&&lx[u]+ly[v]==map[u][v]) { sy[v]=true; if(match[v]==-1||path(match[v])) { match[v]=u; return true; } } return false; } int KM(int n) { int i,j; for(i=0;i<n;i++) { lx[i]=-INF; ly[i]=0; for(j=0;j<n;j++) if(lx[i]<map[i][j]) lx[i]=map[i][j]; } memset(match,-1,sizeof(match)); for(int u=0;u<n;u++) while(1) { memset(sx,0,sizeof(sx)); memset(sy,0,sizeof(sy)); if(path(u)) break; int dmin=INF; for(i=0;i<n;i++) if(sx[i]) for(j=0;j<n;j++) if(!sy[j]) dmin=MIN(lx[i]+ly[j]-map[i][j],dmin); for(i=0;i<n;i++) { if(sx[i]) lx[i]-=dmin; if(sy[i]) ly[i]+=dmin; } } int sum=0; for(j=0;j<n;j++) sum+=map[match[j]][j]; return sum; } void init(int n) { int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++) { if(!map[i][j]) map[i][j]=INF; } } char s[10010],tmp[10010]; double ans[35]; int main() { int i,j; int t,n,k,m; char str[5]; scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&k,&m); for(i=0;i<n;i++) { scanf("%1s",str); s[i]=str[0]; } s[i]='\0';//printf("%s\n",s); for(i=0;i<m;i++) { memset(map,0,sizeof(map)); for(j=0;j<n;j++) { scanf("%1s",str); tmp[j]=str[0]; } tmp[j]='\0'; for(j=0;j<n;j++) map[s[j]-'A'][tmp[j]-'A']++; //init(30); int res=KM(26); ans[i]=1.0*res/n; } for(i=0;i<m;i++) printf("%.4lf\n",ans[i]); } return 0; }