3.30 二分图

什么是二分图?

二分图的定义是:
设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。简而言之,就是顶点集V可分割为两个互不相交的子集,并且图中每条边依附的两个顶点都分属于这两个互不相交的子集,两个子集内的顶点不相邻。
参考二分图详解

如何判断二分图?

一个图是二分图当且仅当图中不含有奇数环
原理:
证明必要性:
如下图,假如图中存在一个奇数环(即该环上点的个数为奇数)
假设A属于集合0,那么由于A和B相连,B就属于集合1,同理C属于集合0。
然而C与A相连,因此A属于集合1,这和我们的假设矛盾,因此可以说明二分图中一定没有奇数环
3.30 二分图_第1张图片

证明充分性:
创建一种构造方法:
遍历所有点,如果没有被染色,那就将它放在左边的集合中(染成红色),然后遍历该点的所有相连的点,将所有相连的点放到右边的集合中(染成绿色)。直到所有都被染色。
如果这样的方法能够构造成功,那么一定会生成一个二分图。
由于不含有奇数环,因此一定不会矛盾。(不会发生矛盾染色)

如何用代码判断二分图?

根据上面的思想,如果一个图可以在染色中顺畅地无误地染色完成,那就说明其是二分图。如果不能,则说明其不是二分图

写代码的时候憨比了,把对h的初始化放在了add后面。这样不就等于add之后又初始化h,相当于屁都没做


#include
#include
#include

using namespace std;

const int N=1e5+10;
const int M=2*1e5+10;

int h[N],ne[M],e[M],idx=1;
int colour[N];

int n,m;

void add(int a,int b){
    
    e[idx]=b;
    ne[idx]=h[a];
    h[a]=idx;
    idx++;
    
}

//颜色共有1,2两种颜色
int dfs(int u,int c){
    //将节点u染成c颜色
    colour[u]=c;
    
    for(int i=h[u];i!=-1;i=ne[i]){
        int j=e[i];
        if(colour[j]==0){
            //如果未被染色
            if(!dfs(j,3-c))   return 0;
        }
        else if(colour[j]==c)   return 0;
    }
    return 1;
}


int main(){
    
    cin>>n>>m;
    memset(h,-1,sizeof h);
    
    for(int i=1;i<=m;i++){
        int a,b;
        cin>>a>>b;
        add(a,b);add(b,a);
    }
    
    
    int flag=1;
    
    for(int i=1;i<=n;i++){
        if(!colour[i]){
            if(!dfs(i,1)){
                flag=0;
                break;
            }
        }
    }
    
    if(flag==0)
        cout<<"No"<<endl;
    else
        cout<<"Yes"<<endl;
    
    return 0;
}

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

什么是最大匹配?

二分图的匹配:给定一个二分图 G,在 G的一个子图 M中,M的边集 {E}中的任意两条边都不依附于同一个顶点,则称 M是一个匹配。
二分图的最大匹配:所有匹配中包含边数最多的一组匹配被称为二分图的最大匹配,其边数即为最大匹配数。

匈牙利算法思路

把二分图的左边集合看作男生,右边集合看作女生,集合之间的连线看作男生女生互有好感,每次确定一条联系就是双方真正谈恋爱。这样每一个匹配都是一个男生和一个女生谈,双方同时都不能和另外的人谈,这样就符合匹配的定义。
匈牙利算法的过程就是,遍历所有的男生(或女生),对于那些没有谈恋爱的男生,找和他互有好感的女生(即查找自己连接的边),如果那个女生当前没有谈恋爱,那么太好了!就让这一对谈恋爱。(即构成一对匹配)
如果那个女生谈恋爱了,那么这个男生也不能放弃,他需要找到现在和这个女生谈恋爱的男生A,问他能不能找别人谈,如果A同时也和其他人有好感并且对方没有谈恋爱,那么就让A和另一个女生谈,这个男生就能追到心仪的女孩了。
就这样匹配下去,直到没人可谈了。

可以看出算法时间复杂度是O(n*m),n是左边子集数量,m是右边子集数量

你可能感兴趣的:(机试备考,深度优先,算法,图论)