二分图:是图论中的一种特殊模型。若能将无向图G=(V,E)的顶点V划分为两个交集为空的顶点集,并且任意边的两个端点都分属于两个集合,则称图G为一个为二分图。
那么二分图有什么用处呢?
举个例子:hdu4751,一堆人,每个人单方面认识一些人,希望把这些人分成两堆,使得每一堆的人都相互认识。根据不认识关系建立图,判断是否是一个二分图。
因为要把人分为两堆,一堆的人是认识的,所以我们建立边的关系的时候建立的是不是相互认识的两个人的关系。
还有,图不一定是联通的,要遍历每一个节点。
#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdio.h>
#include <math.h>
using namespace std;
const int N = 505;
int m,n;
int color[N];
int edge[N][N];
bool dfs(int v, int c){
color[v] = c; //将当前顶点涂色
for(int i = 0; i < n; i++){ //遍历所有相邻顶点,即连着的点
if(edge[v][i] == 1){ //如果顶点存在
if(color[i] == c) //如果颜色重复,就返回false
return false;
if(color[i] == 0 && !dfs(i,-c)) //如果还未涂色,就染上相反的颜色-c,并dfs这个顶点,进入下一层
return false; //返回false
}
}
return true; //如果所有顶点涂完色,并且没有出现同色的相邻顶点,就返回true
}
void solve(){
for(int i = 0; i < n; i++){
if(color[i] == 0){
if(!dfs(i, 1)){
printf("NOT BICOLORABLE.\n");
return;
}
}
}
printf("BICOLORABLE.\n");
}
int main(){
int u,v;
while(cin >> n >> m){
memset(color, 0, sizeof(color));
memset(edge, 0, sizeof(edge));
for(int i = 0; i < m; i++){
cin >> u >> v; //因为是无向图,所以要往两个方向添加边
edge[u][v] = 1; //正着添加
edge[v][u] = 1; //反着添加
}
solve();
}
return 0;
}