zoukankan      html  css  js  c++  java
  • 二分图的最大匹配问题

    设G=(V,E)是一个图,M是E的一个子集,如果M不含环且任意两边都不相邻,则称M为G的一个匹配。G中边数最多的匹配称为G的最大匹配。 对于图G=(V,E),在每条边e上赋一个实数权w(e)。设M是G的一个匹配。定义 ,并称之为匹配M的权。G中权最大的匹配称为G的最大权匹配。如果对一切,e∈E,w(e)=1,则G的最大权匹配就是G的最大匹配。

    匹配

    设M是图G=(V,E)的一个匹配,vi∈V。若vi与M中的边相关联,则称vi是M饱和点,否则称vi为M非饱和点。 如果G中每个顶点都是M饱和点,则称M为G的完美匹配。 设M是G的一个匹配,P是G的一条链。如果P的边交替地一条是M中的边,一条不是M中的边,则称P为M交错链。类似地,我们可以定义G的交错圈。易知,G的交错圈一定是偶圈。 一条连接两个不同的M非饱和点的M交错链称为M增广链。 两个集合S1与S2的“异或”操作S1⊕S2是指集合S1⊕S2=(S1∩S2)\(S1∪S2) 容易看出,设M是G的匹配,P是G中的M增广链、则M⊕P也是G的匹配,而且 可以证明,G中匹配M是最大匹配当且仅当G中没有M增广链。

    最小路径覆盖=最小路径覆盖=|G|-最大匹配数

    在一个N*N的有向图中,路径覆盖就是在图中找一些路经,使之覆盖了图中的所有顶点,
    且任何一个顶点有且只有一条路径与之关联;(如果把这些路径中的每条路径从它的起始点走到它的终点,
    那么恰好可以经过图中的每个顶点一次且仅一次);如果不考虑图中存在回路,那么每每条路径就是一个弱连通子集.
    eg. 图4*4的图G的最小路径覆盖,包含2条路径: p1->p3, p2->p4

    由上面可以得出:

    1.一个单独的顶点是一条路径;
    2.如果存在一路径p1,p2,......pk,其中p1 为起点,pk为终点,那么在覆盖图中,顶点p1,p2,......pk不再与其它的
       顶点之间存在有向边.

    最小路径覆盖就是找出最小的路径条数,使之成为G的一个路径覆盖.

    路径覆盖与二分图匹配的关系:最小路径覆盖=|G|-最大匹配数;

    其中最大匹配数的求法是把G中的每个顶点pi分成两个顶点pi'与pi'',如果在p中存在一条pi到pj的边,那么在
    二分图G'中就有一条连接pi'与pj''的无向边;这里pi' 就是p中pi的出边,pj''就是p中pj 的一条入边;

    对于公式:最小路径覆盖=|G|-最大匹配数;可以这么来理解;

    如果匹配数为零,那么P中不存在有向边,于是显然有:
    最小路径覆盖=|G|-最大匹配数=|G|-0=|G|;即P的最小路径覆盖数为|G|;

    G'中不在于匹配边时,路径覆盖数为|G|;

    如果在G'中增加一条匹配边pi'->pj'',那么在图P的路径覆盖中就存在一条由pi连接pj的边,也就是说pi与pj 在
    一条路径上,于是路径覆盖数就可以减少一个;如此继续增加匹配边,每增加一条,路径覆盖数就减少一条;
    直到匹配边不能继续增加时,路径覆盖数也不能再减少了,此时就有了前面的公式;但是这里只是说话了每条匹配边
    对应于路径覆盖中的一条路径上的一条连接两个点之间的有向边;下面来说明一个路径覆盖中的每条连接两个顶点之
    间的有向边对应于一条匹配边。

    3。二分图最大独立集=顶点数-二分图最大匹配

    独立集:图中任意两个顶点都不相连的顶点集合。

    题目:

    Girls and Boys

    Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 3260    Accepted Submission(s): 1405

    Problem Description

    the second year of the university somebody started a study on the romantic relations between the students. The relation “romantically involved” is defined between one girl and one boy. For the study reasons it is necessary to find out the maximum set satisfying the condition: there are no two students in the set who have been “romantically involved”. The result of the program is the number of students in such a set.
    The input contains several data sets in text format. Each data set represents one set of subjects of the study, with the following description:
    the number of students
    the description of each student, in the following format
    student_identifier:(number_of_romantic_relations) student_identifier1 student_identifier2 student_identifier3 ...
    or
    student_identifier:(0)
    The student_identifier is an integer number between 0 and n-1, for n subjects.
    For each given data set, the program should write to standard output a line containing the result.

    Sample Input

    7 0: (3) 4 5 6 1: (2) 4 6 2: (0) 3: (0) 4: (2) 0 1 5: (1) 0 6: (2) 0 1 3 0: (2) 1 2 1: (1) 0 2: (1) 0

    Sample Output

    5 2

    题目大意:给你每个人互相认识的人,然后问最多能找到多少个人都互不认识。其实就是找:最大独立集合!

    已知:二分图最大独立集合 = 节点数 - 最大匹配数

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=1068

    代码:

    #include <iostream>
    using namespace std;
    int visit[1001];
    int match[1001]; //记录当前与之相连的边
    bool maps[1001][1001]; //记录两点有相连的边,有则为true
    int N;
    
    bool dfs(int k) //从k出发找增广路径 //匈牙利算法
    {
        for(int i =0;i<N;i++)
        {
            if(maps[k][i]&& !visit[i]) //k,i相邻,并且没有访问过
            {
                visit[i] = true;
                if(match[i] ==-1 || dfs(match[i])) //如果i没有匹配过或者i在匹配中,从i出发可以有增广路径
                {
                    match[i] = k;
                    return true;
                }
            }
        }
        return false;
    }
    int MaxMatch()  //找最大匹配数
    {
        int num = 0;
        memset(match,-1,sizeof(match));
        for(int i=0; i<N; ++i)
        {
            memset(visit,0,sizeof(visit));
            if(dfs(i)) ++num;
        }
        return num;
    }
    
    int main()
    {
        int i,j;
        int x,y,n;
        int ans;
        while(cin>>N)
        {
            memset(maps,0,sizeof(maps));
            for(i =0 ;i<N;i++)
            {
                scanf("%d: (%d)",&x,&n);
                for(j =0;j<n;j++)
                {
                    scanf("%d",&y);
                    maps[x][y] = true;
                }
            }                                ////二分图具有对称性,最大匹配数 /= 2 
            printf("%d\n",N-MaxMatch()/2); //因为x,y是相对的,就有2倍
        }
        return 0;
    }
  • 相关阅读:
    设计模式----单例模式
    C++ 派生类
    C++ 操作符
    构造,清理,拷贝和移动
    php的yii框架开发总结10
    php的yii框架开发总结9
    php的yii框架开发总结8
    php的yii框架开发总结7
    php的yii框架开发总结6
    php的yii框架开发总结5
  • 原文地址:https://www.cnblogs.com/cheng07045406/p/3132171.html
Copyright © 2011-2022 走看看