hdu 3718 Similarity 二分图最大权匹配

来源:互联网 发布:上网记录查询软件 编辑:程序博客网 时间:2024/06/05 21:13
/*二分图 最大权匹配问题,题目给定条件可以看出是完备匹配;利用最小费用最大流解决X集合连源点,边权为1,花费0Y集合连汇点,边权为1,花费0X连Y中任意元素,边权为1,花费为权值的相反数最后得到的最小费用就是最大权匹配*/#include <stdio.h>#include <iostream>#include <string.h>#include<queue>#include<cmath>using namespace std;const int M=20010,ME=500000;const int INF=0x3f3fffff;//******************************int Head[M],Next[ME],Num[ME],Flow[ME],Cap[ME],Cost[ME],Q[M],InQ[M],Len[M],pre_edge[M];class MaxFlow{public:    void clear()    {memset(Head,-1,sizeof(Head));memset(Flow,0,sizeof(Flow));    }    void addedge(int u,int v,int cap,int cost)    {        Next[top] = Head[u];        Num[top] = v;        Cap[top] = cap;        Cost[top] = cost;        Head[u] = top++;         Next[top] = Head[v];        Num[top] = u;        Cap[top] = 0;        Cost[top] = -cost;        Head[v] = top++;    }    int solve(int s,int t) //返回最终的cost    {        int cost = 0;        while(SPFA(s,t))        {            int cur = t,minflow = INF;            while(cur != s)            {                if(minflow > Cap[pre_edge[cur]]-Flow[pre_edge[cur]])                    minflow = Cap[pre_edge[cur]]-Flow[pre_edge[cur]];                cur = Num[pre_edge[cur] ^ 1];            }            cur = t ;            while(cur != s)            {                Flow[pre_edge[cur]] += minflow;                Flow[pre_edge[cur] ^ 1] -= minflow;                cost += minflow * Cost[pre_edge[cur]];                cur = Num[pre_edge[cur] ^ 1];            }        }        return cost;    }private:    bool SPFA(int s,int t)    {        fill(Len,Len+M,INF);        Len[s]=0;        int head = -1,tail = -1,cur;        Q[++head] = s;        while(head != tail)        {            ++tail;            if(tail >= M) tail = 0 ;            cur = Q[tail];            for(int i = Head[cur];i != -1;i = Next[i])            {                if(Cap[i]>Flow[i] && Len[Num[i]] > Len[cur] + Cost[i])                {                    Len[Num[i]] = Len[cur] + Cost[i];                    pre_edge[Num[i]] = i;                    if(!InQ[Num[i]])                    {                        InQ[Num[i]]=true;                        ++head;                        if(head >= M) head = 0;                        Q[head] = Num[i];                    }                }            }            InQ[cur]=false;        }        return Len[t] != INF;    }    int top;}my;//******************************int n,m,k;char ans[10009][2];char mo[10009][2];int flow[40][40];int main(){int ca;scanf("%d",&ca);while(ca--){scanf("%d%d%d",&n,&m,&k);for(int i=0;i<n;i++){scanf("%s",ans[i]);}while(k--){my.clear();memset(flow,0,sizeof(flow));for(int i=0;i<n;i++){scanf("%s",mo[i]);flow[ans[i][0]-'A'+1][mo[i][0]-'A'+1]++;}for(int i=1;i<=26;i++){for(int j=1;j<=26;j++)my.addedge(i,j+26,1,-flow[i][j]);my.addedge(0,i,1,0);my.addedge(i+26,53,1,0);}printf("%.4lf\n",-my.solve(0,53)*1.0/(1.0*n));}}    return 0;}

原创粉丝点击