二分图

作者: Anxdada | 来源:发表于2017-02-23 20:10 被阅读0次

说说二分图,其实图论的题难点不在用算法,难在如何建图,只有图建好了,剩下的就简单了,在这说说求二分图的算法,即匈牙利算法,其实一点都不难,也很好理解拿笔写写就行了.

二分图最大匹配----匈牙利算法

重要的一点就是看出来了用二分图做,然后就是建图了,再然后适当修改Find函数就行了.

int n,m;
int link[1001];
bool vis[1001];
vector<int>data[1001];
bool Find(int x)
{
    for(int i=0;i<data[x].size();i++){
        int m=data[x][i];
        if(!vis[m]){
            vis[m] = true;
            if(!link[m] || Find(link[m])){
                link[m] = x;
                link[x] = m;
                return true;
            }
        }
    }
    return false;
}

模板题
AC代码:

#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
#define CLR(x) memset(x,0,sizeof(x))
int n,m;
int link[1001];
bool vis[1001];
vector<int>data[1001];
bool Find(int x)
{
    for(int i=0;i<data[x].size();i++){
        int m=data[x][i];
        if(!vis[m]){
            vis[m] = true;
            if(!link[m] || Find(link[m])){
                link[m] = x;
                link[x] = m;
                return true;
            }
        }
    }
    return false;
}
int main()
{
    scanf("%d%d",&n,&m);
    CLR(link);
    int ans=0;
    for(int i=0;i<m;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        data[u].push_back(v);
        data[v].push_back(u);
    }
    for(int i=1;i<=n;i++)
    {
        CLR(vis);
        if(!link[i] && Find(i))   //记住判断的先后逻辑顺序!!!
            ans++;
    }
    printf("%d\n", ans);
}

这里有些重要的定理,有许多题经过建图后发现就是求这些,故常常配合着这个二分图来运算需要记住!!!
(通过一些小的改变即可达到要求)
定理:
定理1:最大匹配数M = 最小点覆盖数
定理2:最大独立集 = 顶点数 - 最大匹配数
定理3:有向图最小路径覆盖数 = 顶点数 - 最大匹配数
定理4:无向图最小路径覆盖数 = 顶点数 - 最大匹配数/2
(因为处理过两次)
对以上名词的一些解释:
最大匹配数:最大匹配的匹配边的数目
最小点覆盖数:选取最少的点,使任意一条边至少有一个端点被选择
最大独立集:选取最多的点,使任意所选两点均不相连
最小路径覆盖数:对于一个 DAG (有向无环图),选取最少条路径,使得每个顶点属于且仅属于一条路径。路径长可以为 0 (即单个点).
证明略.

二分图判定----染色法
模板题在此

染色法判断是否是二分图.

AC代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define CLR(x) memset(x,0,sizeof(x))
const int maxn=1e4+5;
int cas=1;
bool flag;
int n,m;
bool vis[maxn][maxn];   //vis[i][j] 表示 i 到 j 是否相连过.是的话数组值为1,否则为 0 .
vector<int>ve[maxn];
int color[maxn];
void dfs(int x,int col)
{
    if(!flag) return ;   //flag=false, 后面就都没有必要再搜下去了.
    if(!color[x]) color[x]=col;  //如果该点没有被染色,就染上.
    else if(color[x]!=col){   //如果遇到将要染色的点不等于将要被染的色,则结束dfs,不是二分图.
        flag=false;
        return ;
    }
    for(int i=0;i<ve[x].size();i++)
    {
        int next=ve[x][i];
        if(!vis[x][next] && !vis[next][x]){
            vis[x][next]=1;
            dfs(next,3-col);
        }
    }
}
int main()
{
    int t;
    cin >> t;
    while(t--){
       flag=true;
       scanf("%d %d",&n,&m);
       CLR(color);
       CLR(vis);
       for(int i=1;i<=n;i++)
           ve[i].clear();
       for(int i=0;i<m;i++){
            int u,v;
            scanf("%d %d",&u,&v);
            ve[u].push_back(v);
            ve[v].push_back(u);
        }
        for(int i=1;i<=n;i++)
        {
            if(!color[i]) dfs(i,1);    //循环染色.  分别左边染1,右边染2 .
        }
        if(flag) printf("Correct\n");
        else
            printf("Wrong\n");
    }
}

相关文章

  • 二分匹配 专题整理

    二分匹配学习记录 参考资料 二分图讲解及匈牙利模板 HDU 2444 题意 给出图,求是否二分图,和二分图的最大匹...

  • 【算法篇】二分图匹配之匈牙利算法

    二分图匹配,自然要先从定义入手,那么二分图是什么呢? 二分图: 二分图又称作二部图,是图论中的一种特殊模型。 设G...

  • 算法学习之路|二分图的最大匹配—匈牙利算法(Dfs实现)

    摘要:二分图的概念:二分图又称作二部图,是图论中的一种特殊模型 二分图的概念:二分图又称作二部图,是图论中的一种特...

  • 二分图基础知识

    前言:总结一下二分图相关的知识点 0X00 基础 判断是不是二分图 785. 判断二分图 DFS 遍历所有节点,遍...

  • 基于图的personal rank推荐算法

    背景 用户的行为很容易表示为图定点,边 uesr,item构建图(二分图)二分图:又称为二部图,是图论中的一种特...

  • LeetCode 785. 判断二分图

    题目 785. 判断二分图 描述 给定一个无向图graph,当这个图为二分图时返回true。如果我们能将一个图的节...

  • 二分图

    二分图判定: 题目链接:二分图判定 dfs: 最大匹配: 题目链接:最大匹配-匈牙利算法 dfs: 二维最大匹配:...

  • 二分图

    说说二分图,其实图论的题难点不在用算法,难在如何建图,只有图建好了,剩下的就简单了,在这说说求二分图的算法,即匈牙...

  • 785. 判断二分图

    785. 判断二分图 染色法

  • 二分图

    二分图一些常用结论:最小支配集:V* 中最少的点,关联最多(V-V* )中的点;最小点覆盖:用最少的点去覆盖完所有...

网友评论

      本文标题:二分图

      本文链接:https://www.haomeiwen.com/subject/gwsbwttx.html