二分图&全家桶(完善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;
}

浙公网安备 33010602011771号