二分图&全家桶(完善ing)

开始图论板块,二分图

二分图

也叫二部图,图论里面的特殊模型,将顶点分成两个集合,集合里面的点没有任何直接关联,换言之,将图分成两部分,每部分的顶点之间都没有边直接关联

二分图充分必要条件

1、至少两个顶点
2、所有回路长度均为偶数
推论:任何无回路的图均是二分图。

这个图是二分图吗?

再看看?

这个图是二分图吗?

再看看?

染色法判断二分图

如何去判断二分图呢,从一个点开始染色,周围的点都染成不同的颜色,如果出现颜色相同的相邻点,则不是二分图。
原理基于二分图的充要条件
1、如果不存在回路,染色不会出现相同情况,0101010,,
2、存在回路,必然是偶数回路,这样才能保证不出现相同,0101这样的环可以满足,如果是奇数,01010,首尾相同不符合条件。

模板题
Des
给出一个图,是否能出现一种方法将他分成二分图,输出图的两部分,否则输出-1。
Code

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int cnt, head[N];
struct edge
{
    int to, nex;
} e[N << 1];
inline void add_edge(int u, int v)
{
    e[++cnt].to = v;
    e[cnt].nex = head[u];
    head[u] = cnt;
}
int n, m, col[N];
vector<int> v1, v2;
bool dfs(int u)
{
    for(int i = head[u]; i; i = e[i].nex)
    {
        int v = e[i].to;
        if(!col[v])
        {
            col[v] = 3 - col[u];
            if(!dfs(v)) return false;
        }
        if(col[v] == col[u]) return false;
    }
    return true;
}
signed main()
{
    ios::sync_with_stdio(false), cin.tie(0);
    cin >> n >> m;
    int u, v;
    for(int i = 0; i < m; ++i)
    {
        cin >> u >> v;
        add_edge(u, v);
        add_edge(v, u);
    }
    for(int i = 1; i <= n; ++i)
    {
        if(col[i]) continue;
        if(!col[i])
        {
            col[i] = 1;
            if(!dfs(i))
            {
                cout << "-1\n";
                return 0;
            }
        }
    }
    for(int i = 1; i <= n; ++i)
    {
        if(col[i] == 1) v1.push_back(i);
        else v2.push_back(i);
    }
    cout << v1.size() << "\n";
    for(int i = 0; i < v1.size(); ++i) cout << v1[i] << " \n"[i == v1.size() - 1];
    cout << v2.size() << "\n";
    for(int i = 0; i < v2.size(); ++i) cout << v2[i] << " \n"[i == v2.size() - 1];
    return 0;

}

二分图的最大匹配

posted @ 2022-07-07 19:41  std&ice  阅读(84)  评论(0)    收藏  举报