码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-07-09 10:56:09      阅读:102      评论:0      收藏:0      [点我收藏+]

标签:name   增加   元素   ++   ||   algo   tor   开始   bit   

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

 

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

染色法判定:从某点开始染色为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

 

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

标签:name   增加   元素   ++   ||   algo   tor   开始   bit   

原文地址:https://www.cnblogs.com/op-z/p/11155859.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!