hdu 3718 KM最优匹配

来源:互联网 发布:vscode git 记住密码 编辑:程序博客网 时间:2024/05/16 09:00

建图过程,上面一行字母与下面一行一一对应连边,再利用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 50int 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;}
原创粉丝点击