HDU 3718 Similarity【KM算法】

来源:互联网 发布:电大网站美工设计基础 编辑:程序博客网 时间:2024/05/21 00:52

题目链接

题意:两串字母匹配,求最大权匹配除以长度。

二分图最大权匹配KM算法模板题。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int maxn = 'Z' + 10;const int INF = 0x3f3f3f3f;//接口:KM()//输入:w[][]   全局变量,表示带权图//     pop     全局变量,表示图一侧的点数//输出:最大权匹配的值//     son_y[] 全局变量,表示匹配方案int T;int n, m, k;char s[10010];char ss[10010];int w[maxn][maxn], x[maxn], y[maxn];int prev_x[maxn], prev_y[maxn], son_y[maxn], slack[maxn], par[maxn];int lx, ly, pop;void init(){    memset(w, 0, sizeof(w));    memset(x, 0, sizeof(x));    memset(y, 0, sizeof(y));    memset(prev_x, 0, sizeof(prev_x));    memset(prev_y, 0, sizeof(prev_y));    memset(son_y, 0, sizeof(son_y));    memset(slack, 0, sizeof(slack));    memset(par, 0, sizeof(par));}void adjust(int v){    son_y[v] = prev_y[v];    if (prev_x[son_y[v]] != -2)        adjust(prev_x[son_y[v]]);}bool find(int v){    for (int i = 0; i < pop; i++)    {        if (prev_y[i] == -1)        {            if (slack[i] > x[v] + y[i] - w[v][i])            {                slack[i] = x[v] + y[i] - w[v][i];                par[i] = v;            }            if (x[v] + y[i] == w[v][i])            {                prev_y[i] = v;                if (son_y[i] == -1)                {                    adjust(i);                    return true;                }                if (prev_x[son_y[i]] != -1)   continue;                prev_x[son_y[i]] = i;                if (find(son_y[i])) return true;            }        }    }    return false;}int KM()//接口{    int i, j, m;    for (i = 0; i < pop; i++)    {        son_y[i] = -1;        y[i] = 0;    }    for (i = 0; i < pop; i++)    {        x[i] = 0;        for (j = 0; j < pop; j++)            x[i] = max(x[i], w[i][j]);    }    bool flag;    for (i = 0; i < pop; i++) {        for (j = 0; j < pop; j++)        {            prev_x[j] = prev_y[j] = -1;            slack[j] = INF;        }        prev_x[i] = -2;        if (find(i))    continue;        flag = false;        while (!flag)        {            m = INF;            for (j = 0; j < pop; j++)                if (prev_y[j] == -1)                    m = min(m, slack[j]);            for (j = 0; j < pop; j++)            {                if (prev_x[j] != -1)    x[j] -= m;                if (prev_y[j] != -1)    y[j] += m;                else    slack[j] -= m;            }            for (j = 0; j < pop; j++)            {                if (prev_y[j] == -1 && !slack[j])                {                    prev_y[j] = par[j];                    if (son_y[j] == -1)                    {                        adjust(j);                        flag = true;                        break;                    }                    prev_x[son_y[j]] = j;                    if (find(son_y[j]))                    {                        flag = true;                        break;                    }                }            }        }    }    int ans = 0;    for (int i = 0; i < pop; i++)        ans += w[son_y[i]][i];    return ans;}int main(){    scanf("%d", &T);    while (T--)    {        scanf("%d %d %d", &n, &m, &k);        for (int i = 0; i < n; i++)            scanf(" %c", &s[i]);        while (k--)        {            for (int i = 0; i < n; i++)                scanf(" %c", &ss[i]);            init();            for (int i = 0; i < n; i++)                w[s[i] - 'A'][ss[i] - 'A']++;            pop = 26;            double ans = (double)KM() / (double)n;            printf("%.4f\n",ans);        }    }}


原创粉丝点击