hdu 3718Similarity(二分图最大权匹配)

来源:互联网 发布:招生软件 编辑:程序博客网 时间:2024/06/06 00:43
//hdu 3718//两个字符串的最大相似度//容易看出,字符与字符只能一一对应//如果字符i与字符j对应,那么权值就为此类对应存在的数量。#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<iostream>using namespace std;#define clr(a) memset(a,0,sizeof(a))const int N=500;const int INF=1<<28;int G[500][500];struct KM{    int lx[N],ly[N];//顶标    int visx[N],visy[N];    int line[N];    int we[N];//已配对所对应边权值    int nx,ny;    int slack;    bool find(int u){        visx[u]=true;        for(int v=1;v<=ny;v++){            if(!visy[v])//v不在相等子图中            {                int t=lx[u]+ly[v]-G[u][v];                if(t==0){                    visy[v]=1;                    if(line[v]==-1||find(line[v])){                        line[v]=u;                        we[v]=G[u][v];                        return 1;                    }                }                else if(t<slack)                    slack=t;            }        }        return 0;    }    bool km(){//返回是否完备匹配        clr(lx);clr(ly);        //memset(lx, -INF, sizeof(lx));        //memset(ly, -INF, sizeof(ly));        memset(line,-1,sizeof(line));        for(int i=1;i<=nx;i++){            for(int j=1;j<=ny;j++){                if(G[i][j]>lx[i])                    lx[i]=G[i][j];//初始化为xi所连接的最大权值            }        }        for(int u=1;u<=nx;u++)        {            while(true){                slack=INF;                clr(visx);clr(visy);                if(find(u))break;                if(slack==INF)return 0;                for(int i=1;i<=nx;i++){                    if(visx[i])lx[i]-=slack;                }                for(int i=1;i<=ny;i++){                    if(visy[i])ly[i]+=slack;                }            }        }        return 1;    }    int best_match(){        int res=0;        km();        for(int u=1;u<=ny;u++){            if(line[u]==-1)continue;            res+=we[u];        }        return res;    }}kk;char dic[10010],dic2[10100];int id1[10010],id2[10100];int vis[10010];int main(){    int t;    scanf("%d",&t);    while(t--){        int n,k,m;        scanf("%d%d%d",&n,&k,&m);        int cnt1=0,cnt2=0;        char s[2];        clr(vis);        for(int i=0;i<n;i++){            scanf("%s",s);            dic[i]=s[0];            int x=dic[i]-'A'+1;            if(!vis[x]){                vis[x]=1;                id1[dic[i]]=++cnt1;            }        }        while(m--){            clr(vis);            cnt2=0;            for(int i=0;i<n;i++){                scanf("%s",s);                dic2[i]=s[0];                int x=dic2[i]-'A'+1;                if(!vis[x]){                    vis[x]=1;                    id2[dic2[i]]=++cnt2;                }            }            clr(G);            for(int h=0;h<n;h++){                int j=id2[dic2[h]],k=id1[dic[h]];                G[j][k]++;            }            kk.nx=cnt2,kk.ny=cnt1;            double ans=kk.best_match()*1.0/n;            printf("%.4lf\n",ans);        }            }    return 0;}

0 0
原创粉丝点击