SCU2016-01 H题 (二分图带权匹配 KM算法)

原创 2016年08月30日 11:16:52

分析:

裸的求最大匹配和。
如果是求最大配积的话,可以先求权值的自然对数的最大匹配和,最后的最大匹配和再取e的幂次就可,当然有精度问题。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define pr(x) cout << #x << ": " << x << "  " 
#define pl(x) cout << #x << ": " << x << endl;

const int M = 101, INF = int(1e9);

int n, A[109];
int w[M][M];            // 保存权值  
int lx[M], ly[M];       // 可行顶标  
int pre[M], slack[M];   // 父节点、保存修改量  
bool visx[M], visy[M];  

int DFS(int x)  
{  
    visx[x] = 1;  
    for(int y = 1; y <= n; y ++){  
        if(visy[y])  
            continue;  

        int t = lx[x] + ly[y] - w[x][y];  
        if(t == 0){                 // 说明是相等子图  
            visy[y] = 1;  
            if(pre[y] == -1 || DFS(pre[y])){  
                pre[y] = x;  
                return 1;           // 找到增广轨  
            }  
        }  
        else if(slack[y] > t){       // 不在相等子图中slack 取最小的  
            slack[y] = t;  
        }  
    }  

    return 0;       // 没有找到增广轨(说明顶点x没有对应的匹配,与完备匹配(相等子图的完备匹配)不符)  
}  

int KM()  
{  
    int i, j;  
    memset (pre, -1, sizeof(pre));  
    memset (ly, 0, sizeof(ly));  
    for(i = 1; i <= n; i ++){            // lx初始化为与它关联边中最大的  
        for(j = 1, lx[i] = -INF; j <= n; j ++){  
            if(w[i][j] > lx[i])  
                lx[i] = w[i][j];  
        }  
    }  

    for(int x = 1; x <= n; x ++){  
        for(i = 1; i <= n; i ++){        // slack 初始化  
            slack[i] = INF;  
        }  

        while(1){  
            memset (visx, 0, sizeof(visx));         // vis 初始化  
            memset (visy, 0, sizeof(visy));  

            if (DFS(x)){                // 若成功(找到了增广轨),则该点增广完成,进入下一个点的增广  
                break;                  // 若失败(没有找到增广轨),则需要改变一些点的顶标,使得图中可行边的数量增加。  
            }                           // 方法为:将所有在增广轨中(就是在增广过程中遍历到)的X方点的标号全部减去一个常数d,  
                                        // 所有在增广轨中的Y方点的标号全部加上一个常数d  
            int d = INF;  
            for(i = 1; i <= n; i ++){  
                if(!visy[i] && d > slack[i])  
                    d = slack[i];  
            }  

            for(i = 1; i <= n; i ++){  
                if(visx[i])  
                    lx[i] -= d;  
            }  

            for(i = 1; i <= n; i ++){    // 修改顶标后,要把所有不在交错树中的Y顶点的slack值都减去d  
                if(visy[i])  
                    ly[i] += d;  
                else  
                    slack[i] -= d;  
            }  
        }  
    }  

    int res = 0;  
    for(i = 1; i <= n; i ++){  
        if(pre[i] > -1)  
            res += w[pre[i]][i];  
    }  

    return res;  
}  

/*
int main ()  
{  
    while(scanf("%d", &n) != EOF){  
        for(int i = 1; i <= n; i ++){  
            for(int j = 1; j <= n; j ++){  
                scanf("%d", &w[i][j]);  
            }  
        }  

        int ans = KM();  
        printf("%d\n", ans);  
    }  

    return 0;  
}  
*/



struct jibancanyang
{

    void fun() {
        while (scanf("%d", &n)) {
            if (!n) break;
            for (int i = 1; i <= n; ++i) {
                scanf("%d", &A[i]);
            }
            for (int i = 1; i <= n; ++i) {
                for (int j = 1; j <= n; ++j) {
                    char c;
                    cin >> c;
                    if (c == '1') {
                        w[i][j] = A[i] ^ A[j];
                    } else {
                        w[i][j] = 0;
                    }
                }
            }
            printf("%d\n", KM());
        }
    }


}ac;

int main()
{
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif
    ac.fun();
    return 0;
}
版权声明:本文为博主原创文章,转载请注明作者:jibancanyang。

相关文章推荐

二分图带权匹配的KM算法以及费用流建模

从理论上分析,KM算法的时间复杂度比费用流要好,但是实际上和较好的费用流算法比起来运行效率是差不多的,KM算法优势仅仅在于编程容易。而对于十分稀疏的图,许多优秀的费用流算法效率是很高的。这并不说明KM...

HDU3722 Card Game KM算法的二分图带权匹配

Problem Address:http://acm.hdu.edu.cn/showproblem.php?pid=3722 【前言】 又搜刮来了一份代码。 用于求二分图的带权匹...

二分图带权匹配 KM算法与费用流模型建立

转自http://hi.baidu.com/lerroy312/item/42e718ba58a1f8df85dd795f [二分图带权匹配与最佳匹配] 什么是二分图的带权匹配?二分图的带权匹配就...

【模板】KM算法模板(带注释)——二分图带权最大匹配

/*求最小值就把权值全部取相反数, 继续套这个最大值的模板*/ #include #include #include #includeconst int maxn = 101; const int...

二分图带权匹配 KM算法与费用流模型建立

From: https://www.byvoid.com/blog/match-km/ [二分图带权匹配与最佳匹配] 什么是二分图的带权匹配?二分图的带权匹配就是求出一个匹配集合,使得集合...

二分图带权匹配 KM算法与费用流模型建立

[二分图带权匹配与最佳匹配] 什么是二分图的带权匹配?二分图的带权匹配就是求出一个匹配集合,使得集合中边的权值之和最大或最小。而二分图的最佳匹配则一定为完备匹配,在此基础上,才要求匹配的边权值之和最...

HDU 2255 奔小康赚大钱(二分图的最大带权匹配 裸的KM算法)

奔小康赚大钱                                         &#...

带权的二分图的最优匹配KM算法

/********************************************************* 算法引入: 给定一个完全二分图G=(X∪Y,X×Y),其中边(x,y)有权w(x,...
  • Jarily
  • Jarily
  • 2013-02-27 13:34
  • 3254

二分图最大匹配km算法

  • 2013-11-04 19:30
  • 127KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)