zoukankan      html  css  js  c++  java
  • hdu3718(二分图最大权匹配,模板题)

    题意:

      给定模板序列,和m个代考察序列,求出每个序列和模板序列的相似度。

      其中相似度的定义:待考察序列中的相同字母,均可以替换成其他相同字母。例如 A B A A C 可以替换成 B B B B C 或者 C B C C C。或者A A A A A(B C都变成A)。替换完成后,对应位置字母相同的数量 ,除以序列长度即为答案。

    解决:

      每个待考察序列建图,扫一遍序列,图ma[26][26]对应字母替换之后的收益。即为二分图。跑一下KM。

    #include <bits/stdc++.h>
    
    const int MAXN = 40;
    const int INF = 0x3f3f3f3f;
    
    int n, nx, ny;
    int lx[MAXN], ly[MAXN];
    int ma[MAXN][MAXN];
    int slack[MAXN], match[MAXN];
    bool visx[MAXN], visy[MAXN];
    
    bool findPath(int x)
    {
        visx[x] = true;
         for (int y = 1; y <= ny; ++y) {
            if (true == visy[y]) {
                continue;
            }
            int tmp = lx[x] +ly[y] - ma[x][y];
            if (0 == tmp) {
                visy[y] = true;
                if (-1 == match[y] || true == findPath(match[y])) {
                    match[y] = x;
                    return true;
                }
            }
            if (slack[y] > tmp)
                slack[y] = tmp;
         }
         return false;
    }
    
    int km()
    {
        nx = ny = n;
        memset(match, -1, sizeof match);
        memset(ly, 0, sizeof ly);
        for (int x = 1; x <= nx; ++x) {
            lx[x] = -INF;
            for (int y = 1; y <= ny; ++y) {
                lx[x] = std::max(lx[x], ma[x][y]);
            }
        }
        for (int x = 1; x <= nx; ++x) {
            for (int y = 1; y <= ny; ++y) {
                slack[y] = INF;
            }
            while (true) {
                memset(visx, false, sizeof visx);
                memset(visy, false, sizeof visy);
                if (true == findPath(x))
                    break;
                int min_d = INF;
                for (int y = 1; y <= ny; ++y) {
                    if (false == visy[y] && min_d > slack[y]) {
                        min_d = slack[y];
                    }
                }
                for (int x = 1; x <= nx; ++ x) {
                    if (true == visx[x]) {
                        lx[x] -= min_d;
                    }
                }
                for (int y = 1; y <= ny; ++y) {
                    if (true == visy[y]) {
                        ly[y] += min_d;
                    }
                    else
                        slack[y] -= min_d;
                }
            }
        }
        int res = 0;
        for (int y = 1; y <= ny; ++y) {
            if (-1 != match[y]) {
                res += ma[match[y]][y];
            }
        }
        return res;
    }
    
    char pat[10000+10];
    char buf[10000+10];
    
    int main()
    {
        int T;
        scanf("%d", &T);
        while (T--) {
            int l, tmp, m;
            scanf("%d%d%d", &l, &tmp, &m);
            n = 26;
            char cmd[4];
            for (int i = 1; i <= l; ++i) {
                scanf("%s", cmd);
                pat[i] = cmd[0];
            }
            while (m -- ){
                memset(ma, 0, sizeof ma);
                for (int i = 1; i <= l; ++i) {
                    scanf("%s", cmd);
                    buf[i] = cmd[0];
                    ma[pat[i] - 'A' + 1][buf[i] - 'A' + 1]++;
                }
                int res = km();
    //            printf("res = %d
    ", res);
                printf("%.4f
    ", 1.0*res/l);
            }
        }
    }
    View Code
  • 相关阅读:
    SQL SERVER 2000 配置文件 SETUP.INI
    (转)Sybase ASE基础知识:利用Sybase Central简单操作Sybase ASE数据库
    新软发布:Autorun病毒免疫工具
    vc 编程最需要注意的地方
    (转)不得不了解VB中的CallByName
    作业总结
    (转)傻瓜式简单制作Windows7旗舰版免激活光盘镜像教程 (安装后自动激活)
    发布C#模块:平面凸包的计算
    凸包计算模块ConvexHull的使用方法
    模块发布——树类模块
  • 原文地址:https://www.cnblogs.com/takeoffyoung/p/4933961.html
Copyright © 2011-2022 走看看