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算法的描述,基本上可以概括成以下几个步骤: (1) 初始化可行标杆 (...
  • x_y_q_
  • x_y_q_
  • 2016年07月16日 23:17
  • 3616

KM算法求带权二分图的最大匹配(完备匹配)

1.基础知识普及二分图的概念二分图又称作二部图,是图论中的一种特殊 模型。 设G=(V,{R})是一个无向图。如顶点集V可分 割为两个互不相交的子集,并且图中每条边 依附的两个顶点都分属两个不同的子集...
  • makenothing
  • makenothing
  • 2016年02月18日 13:09
  • 1974

km算法(求二分图带权的最大匹配)

1,如果二分图不是完全二分图,我们通过添加无用路径(最大匹配中,路径权值为0)和顶点使之成为完全二分图; 2,使用KM算法求解,KM算法核心需要理解feasible vertex labelin...
  • thy0311
  • thy0311
  • 2015年09月09日 20:03
  • 334

二分图带权匹配-Kuhn-Munkres算法(有修改)

KM算法是通过给每个顶点一个标号(叫做顶标)来把求最大权匹配的问题转化为求完备匹配的问题的。设顶点Xi的顶标为A[i],顶点Yi的顶标为B[i],顶点Xi与Yj之间的边权为w[i,j]。在算法执行过程...
  • mishifangxiangdefeng
  • mishifangxiangdefeng
  • 2012年05月18日 16:47
  • 3209

二分图的最佳完美匹配——KM算法

二分图的最佳完美匹配如果二分图的每条边都有一个权(可以是负数),要求一种完备匹配方案,使得所有匹配边的权和最大,记做最佳完美匹配。(特殊的,当所有边的权为1时,就是最大完备匹配问题) 我们使用KM算...
  • sixdaycoder
  • sixdaycoder
  • 2015年08月17日 15:24
  • 6188

二分图最佳完美匹配——Kuhn-Munkres算法 (最大权匹配)

二分图最大权匹配的代码: #include #include #include #include using namespace std; #define N 100 class So...
  • nisxiya
  • nisxiya
  • 2014年11月12日 16:00
  • 1399

KM算法(二分图完备匹配下的最大权匹配)

阅读本文之前,首先假设您已经理解匈牙利算法,如果不理解友链在这=>我是匈牙利算法...
  • GlassesQ
  • GlassesQ
  • 2016年10月17日 21:02
  • 203

二分图(三)——KM算法

KM算法手工模拟
  • zxn0803
  • zxn0803
  • 2015年11月23日 18:37
  • 4499

二分图带权匹配问题

出处:http://www.byvoid.com/blog/match-km/#respond [二分图带权匹配与最佳匹配] 什么是二分图的带权匹配?二分图的带权匹配就是求出一个匹配集合,...
  • wsniyufang
  • wsniyufang
  • 2011年09月08日 11:39
  • 5875

二分图的最佳匹配(KM 算法)

KM算法求最小权二分匹配,模板题,构图很简单,直接把人当作左边的点,房子当作右边的点, 两者之间的曼哈顿距离当作权值即可。第一次搞带权二分匹配的题,就是用KM算法求最小权的时候要加个处,由于KM求的...
  • weiqubo
  • weiqubo
  • 2011年11月29日 10:44
  • 8254
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:SCU2016-01 H题 (二分图带权匹配 KM算法)
举报原因:
原因补充:

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