二分图带权匹配

来源:互联网 发布:网络女主播不雅视频 编辑:程序博客网 时间:2024/06/05 10:52
#include <cstdio>#include <memory.h>#include <algorithm>    // 使用其中的 min 函数using namespace std;const int MAX = 405;int n;                // X 的大小int weight [MAX] [MAX];        // X 到 Y 的映射(权重)int lx [MAX], ly [MAX],a[MAX],ans[MAX];        // 标号bool sx [MAX], sy [MAX];    // 是否被搜索过int match [MAX];        // Y(i) 与 X(match [i]) 匹配// 初始化权重void init (int size);// 从 X(u) 寻找增广道路,找到则返回 truebool path (int u);// 参数 maxsum 为 true ,返回最大权匹配,否则最小权匹配int bestmatch (bool maxsum = true);void init (int size){    // 根据实际情况,添加代码以初始化    n = size;    int i,j,k,t;    memset(weight,0,sizeof(weight));    for (i=1;i<=n;i++) scanf("%d",&a[i-1]);    for (i=0;i<n;i++)    {        scanf("%d",&k);        for (j=0;j<k;j++)        {            scanf("%d",&t);            weight[i][t-1]=a[i]*a[i];        }    }}bool path (int u){    sx [u] = true;    for (int v = 0; v < n; v ++)        if (!sy [v] && lx[u] + ly [v] == weight [u] [v])            {            sy [v] = true;            if (match [v] == -1 || path (match [v]))                {                match [v] = u;                return true;                }            }    return false;}int bestmatch (bool maxsum){    int i, j;    if (!maxsum)        {        for (i = 0; i < n; i ++)            for (j = 0; j < n; j ++)                weight [i] [j] = -weight [i] [j];        }    // 初始化标号    for (i = 0; i < n; i ++)        {        lx [i] = -0x1FFFFFFF;        ly [i] = 0;        for (j = 0; j < n; j ++)            if (lx [i] < weight [i] [j])                lx [i] = weight [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 dx = 0x7FFFFFFF;            for (i = 0; i < n; i ++)                if (sx [i])                    for (j = 0; j < n; j ++)                        if(!sy [j])                            dx = min (lx[i] + ly [j] - weight [i] [j], dx);            for (i = 0; i < n; i ++)                {                if (sx [i])                    lx [i] -= dx;                if (sy [i])                    ly [i] += dx;                }            }    int sum = 0;    for (i = 0; i < n; i ++)        sum += weight [match [i]] [i];    if (!maxsum)        {        sum = -sum;        for (i = 0; i < n; i ++)            for (j = 0; j < n; j ++)                weight [i] [j] = -weight [i] [j];         // 如果需要保持 weight [ ] [ ] 原来的值,这里需要将其还原        }    return sum;}int main(){    int n,i;    scanf ("%d", &n);    init (n);    int cost = bestmatch (true);    //printf ("%d\n", cost);    //for (i=0;i<n;i++) printf("%d ",match[i]+1);    for (i=0;i<n;i++)    if (weight[match[i]][i]==0) ans[match[i]]=0;else        ans[match[i]]=i+1;    for (i=0;i<n-1;i++) printf("%d ",ans[i]);    printf("%d",ans[n-1]);    return 0;}
0 0
原创粉丝点击