二分圖的判斷與匹配

二分圖:一定沒有奇數環,可能包含長度爲偶數的環, 而且不一定是連通圖

染色法判定二分圖:

採用前向星 + d f s +dfs +dfs的方法。開個 c o l o r color color數組代表染的顏色( 0 0 0表示未被染色, 1 1 1 2 2 2代表兩個顏色)。依次從每個點開始搜索,如果該點未被染色,就開始 d f s dfs dfs搜索,如果返回 0 0 0就說明染色失敗,不是二分圖,標記失敗,跳出循壞。
搜索部分:依次訪問鄰接表可達的每個節點,如果沒有被染色過,就試圖用第二個顏色來染下一個節點,如果被染色過且顏色相同,則染色失敗,返回 0 0 0

代碼:

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,m,u,v,h[N],e[N],ne[N],idx,color[N];
void add(int a,int b){
   
   
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool dfs(int x,int c){
   
   
    color[x]=c;
    for(int i=h[x];i!=-1;i=ne[i]){
   
   
        int j=e[i];
        if(!color[j]){
   
   
            if(!dfs(j,3-c)) return 0;
        }
        else if(color[j]==c) return 0;
    }
    return 1;
}
int main(){
   
   
    memset(h,-1,sizeof h);
    cin>>n>>m;
    while(m--){
   
   
        cin>>u>>v;
        add(u,v),add(v,u);
    }
    bool flag=1; //標記
    for(int i=1;i<=n;i++){
   
   
        if(!color[i]){
   
   
            if(!dfs(i,1)){
   
   
                flag=0;
                break;
            }
        }
    }
    if(flag) puts("Yes");
    else puts("No");
}

二分圖的最大匹配:

二分圖的匹配:給定一個二分圖 G G G,在 G G G的一個子圖 M M M中, M M M的邊集 E {E} E中的任意兩條邊都不依附於同一個頂點,則稱 M M M是一個匹配。

二分圖的最大匹配:所有匹配中包含邊數最多的一組匹配被稱爲二分圖的最大匹配,其邊數即爲最大匹配數。

求最大匹配數:
m a t c h match match數組表示已有的配對。首先遍歷每個點,尋找這個點連通的另一個點,如果另一個點沒有被匹配,那麼就成功預訂配對,如果連通的另一個點有被匹配但是他的匹配節點擁有另一個可選擇匹配的點,那麼就讓另一個可選擇匹配的點去匹配原來的點。
(有點繞)

代碼:

#include<bits/stdc++.h>
using namespace std;
const int N=505,M=1e5+5;
int n1,n2,m,u,v,ne[M],e[M],h[N],idx,match[N],res;
bool st[N];
void add(int a,int b){
   
   
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int find(int x){
   
   
    for(int i=h[x];i!=-1;i=ne[i]){
   
   
        int j=e[i];
        if(!st[j]){
   
   
            st[j]=1;
            if(!match[j]||find(match[j])){
   
   
                match[j]=x;
                return 1;
            }
        }
    }
    return 0;
}
int main(){
   
   
    memset(h,-1,sizeof h);
    cin>>n1>>n2>>m;
    while(m--){
   
   
        cin>>u>>v;
        add(u,v);
    }
    for(int i=1;i<=n1;i++){
   
   
        memset(st,0,sizeof st);
        if(find(i)) res++;
    }
    cout<<res<<endl;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章