原题地址
https://vjudge.net/problem/UVA-10004
题意:对于一张无向图,判断它是不是一张二分图。
解题思路
本题是二分图判定的裸题,首先看二分图的定义:
二分图满足下面的条件:顶点集V可分割为两个互不相交的子集,两个子集内的顶点不相邻。
用2-图着色的观点来看,就是要为每个顶点染色,且使所有相邻的顶点的颜色不同,最小着色数为2的图称为二分图。
选择任意一个顶点出发,依次确定其相邻顶点的颜色。假设为v染上颜色c,如果相邻顶点 i 已经染成了c,那么出现矛盾,不能继续染色,判定失败;如果相邻顶点 i 没有染过色,那么深度优先为它染上颜色-c,根据dfs(i, -c)的返回值判断能否继续染色。
下面的代码用邻接表来表示顶点的邻接情况,graph[i]存储所有与i相邻的顶点编号。
AC代码
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
const int maxn = 205;
vector<int> graph[maxn];
int color[maxn], n;
bool dfs(int v, int c) //判断为顶点v涂上1或-1是否成功
{
color[v] = c; //把顶点v染成c
for (int i = 0; i < graph[v].size(); ++i) //遍历v的邻接顶点
{
if (color[graph[v][i]] == c) //如果邻接顶点同色,染色失败
return false;
if (color[graph[v][i]] == 0 && !dfs(graph[v][i], -c)) //如果邻接顶点还没染色,将其染为-c不成功
return false;
}
return true;
}
void init()
{
memset(color, 0, sizeof(color)); //全部标记为着色
for (int i = 0; i<n; ++i)
graph[i].clear();
}
int main()
{
ios::sync_with_stdio(false);
int m;
while(cin >> n && n)
{
cin >> m;
init(); //初始化
int v1, v2;
for (int i = 0; i<m; ++i)
{
cin >> v1 >> v2;
graph[v1].push_back(v2); //标记邻接
graph[v2].push_back(v1);
}
if (dfs(0,1))
cout << "BICOLORABLE." << endl;
else cout << "NOT BICOLORABLE." << endl;
}
return 0;
}