图论 —— 二分图的判定及最大匹配

Posted op-z

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图论 —— 二分图的判定及最大匹配相关的知识,希望对你有一定的参考价值。

二分图:可将图中顶点分为两个集合,集合内元素独立。

 

判定:至少有两个顶点,若有回路,长度必为偶数。

染色法判定:从某点开始染色为x(-1或1),遍历其所有相邻节点,若未染色,染为-x,否则判断该点颜色,若为x,该图非二分图,退出;为-X则继续遍历。

 

UVA - 10004  Bicoloring

 

技术图片
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<queue>
using namespace std;
typedef long long  ll;
#define me(x) memset(x, -1, sizeof(x))
#define mem(x) memset(x, 0, sizeof(x))
const int MOD = 1e18;
const int N = 2e5 + 5;
struct node

    int to, next, w;
e[N]; //链式前向星存图
int head[N];
int vis[N];
int n, m, id, f;
void ini()

    id=0;
    f=0;
    me(head);
    mem(vis);

void add(int u, int v)

    e[id].to = v;
    e[id].next = head[u];
    head[u] = id++;




void bfs(int x)

    queue<int> q;
    q.push(x);
    vis[x]=-1;
    while(q.size())
    
        x=q.front();
        q.pop();
        for(int i=head[x]; ~i; i=e[i].next)
        
            if(!vis[e[i].to])
            
                q.push(e[i].to);
                vis[e[i].to]=-vis[x];
            
            else
            
                if(vis[e[i].to] == vis[x])
                f=1;break;
            
        
        if(f) break;
    
    return ;

int main()

    int i, j, k;
    int t;
    while(~scanf("%d", &n))
    
        if(!n) return 0;
        ini();
        int u, v;
        scanf("%d", &m);
        for(i=0; i<m; i++)
        
            scanf("%d%d", &u, &v);
            add(u,v);add(v,u);
        
        bfs(0);
        if(f)
        printf("NOT BICOLORABLE.\n");
        else printf("BICOLORABLE.\n");
    
    return 0;
View Code

匹配:边集,集合内的边无公共顶点

最大匹配:二分图中的最大匹配数,即最大无公共顶点边集。

增广路:从未匹配边开始,沿未匹配边--匹配边--未匹配边--匹配边--未匹配边--的交替路

以非匹配边结束,则沿该增广路走匹配数加1

匈牙利算法思想:一直找增广路,增加匹配数,无增广路时匹配数达到最大

 

POJ - 1469 COURSES

技术图片
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<list>
#include<set>
using namespace std;
typedef int ll;
typedef pair<ll,ll> P;
typedef long double ld;
#define mem(x) memset(x, 0, sizeof(x))
#define me(x) memset(x, -1, sizeof(x))
#define fo(i,n) for(i=0; i<n; i++)
#define sc(x) scanf("%d", &x)
#define sca(n,m) scanf("%d%d", &n, &m)
#define pr(x) printf("%d\n", x)
#define pri(x) printf("%d ", x)
#define lowbit(x) x&-x
const ll MOD = 1e9 + 7;
const ll oo = 1e18;
const ll N = 3e3 + 5;
vector<ll> ve[N];
ll vis[N], cy[N];
ll dfs(ll u)

    for(ll i=0; i<ve[u].size(); i++)
    
        if(!vis[ve[u][i]])
        
            vis[ve[u][i]]=1;
            if(!cy[ve[u][i]] || dfs(cy[ve[u][i]])) //找增广路
            
                cy[ve[u][i]]=u;
                return 1;
            
        
    
    return 0;

int main()

    ll i, j, k;
    ll n, m, t;
    ll x;
    sc(t);
    while(t--)
    
        sca(n,m);
        for(i=m+1; i<=m+n; i++)
            ve[i].clear();
        mem(cy);
        for(i=m+1; i<=n+m; i++)
        
            sc(k);
            for(j=0; j<k; j++)
            sc(x),ve[i].push_back(x);
        
        ll ans=0;
        for(i=m+1; i<=n+m; i++)
        
            for(j=1; j<=m; j++) vis[j]=0;
            if(dfs(i)) ans++;
        
        if(ans==n) printf("YES\n");
        else printf("NO\n");
    

    return 0;
View Code

 

以上是关于图论 —— 二分图的判定及最大匹配的主要内容,如果未能解决你的问题,请参考以下文章

图论二分图的应用(染色法判断二分图,最大匹配,最小点覆盖,最大独立集,最小路径点覆盖,最小路径重复点覆盖)

图论二分图的应用(染色法判断二分图,最大匹配,最小点覆盖,最大独立集,最小路径点覆盖,最小路径重复点覆盖)

为啥图论中的最大流算法对于最大二分匹配是正确的

ACwing(基础)--- 匈牙利解决二分图的最大匹配

图论的一些知识点

二分图的最大匹配(匈牙利算法)HDU1083