图论入门———深度优先搜索实现二分图判定
这周开始图论的学习
第一天简要的了解一下图的概念,以及表示、储存的方法。
主要就是邻接矩阵和邻接表两种方式 邻接矩阵就不说了比较好实现
邻接表则主要用到不同的容器,比如vector。
使用邻接表的主要思路是对每一个顶点都建立一个vector容器,当它和另一个顶点有边的时候就将该顶点的编号插入vector中,注意无向表还要反过来插入一次
当使用类或者结构体来储存图的顶点和边时就可以添加众多的属性来扩展
接下来就是图的搜索,先以最基本的深度优先搜索为例 其实很简单,就是一个顶点走到头再回来走下一支
现在有一个基本的问题,我们如何判断一个图是否是二分图呢
最简单的思路无非是穷举,对每个顶点我们都可以有两种颜色,采用搜索的思路,如果能走出一条满足任意两个顶点颜色的路径就可以了。
具体的实现方法参考一下书本,大概可以这样想:
从一个顶点出发,把所有它相邻的顶点染成另一个颜色。不停的继续这一个过程,一层一层的染色。如果中间不出现矛盾情况(即相邻的顶点同色)就判定为二分图,否则立即返回换一个没有染色的顶点重新尝试(这个的原理需要好好理解)
放仿照的代码:
/* 最基础的图论问题,算是对存储结构的熟悉。 二分图判定问题,使用邻接表实现(vector) */ # include<iostream> # include<vector> using namespace std; const int MAX_V = 1000; int V,E; vector<int> G[MAX_V];//新建了一个图,G数组中的每一个元素都是一个顶点,对应着一个vector,其中包含了它指向的顶点。 //没有设定边的属性,仅用一个int表示指向的顶点。 int color[MAX_V];//记录顶点的颜色(只有两种,1或-1) bool dfs(int v,int c) { color[v] = c;//将顶点v染成颜色c for (int i = 0; i < G[v].size(); i++) { if (color[G[v][i]] == c) return false; /* 简要说明: 首先需要理解G[v][i]的含义!是指顶点v的第i条边指向的顶点! 上面的表示,如果相邻的顶点同色,就剪掉这一枝,返回false */ if (color[G[v][i]] == 0 && !dfs(G[v][i], -c)) return false; //如果相邻的顶点还没有染色就把它染成-c } return true; //如果都染色了返回true } void solve() { for (int i = 0; i < V; i++) { if (color[i] == 0) { if (!dfs(i, 1)) { printf("No\n"); return; } } } printf("Yes\n"); } int main() { cin >> V >> E; for (int i = 0; i < E; i++) { int s, t; cin >> s >> t; G[s].push_back(t);//从s向t连边 G[t].push_back(s);//因为是无向图反过来再连接一次 } solve(); //system("pause"); return 0; }