2021-1 判断无向图是否有环 与 判断一个图是否是二分图 c++

构建图的头文件见 Graph.h

判断是否有环

采用dfs搜索,维护三个顶点信息,【上一个已访问节点,当前节点,下一个】。直接的,当【下一个】已经被标记且不是【上一个】,说明有环。因为,被标记节点【上一个】,【下一个】属于一个联通子图,即有路径相连。

Cycle.h

#pragma once
#include"Graph.h"
class Cycle
{
private:
	vector<int>* m_visited = nullptr;
	bool m_hasCycle = false;
	void dfs(Graph& G, int now, int pre);
public:
	Cycle() {}
	Cycle(Graph& G);

	bool hasCycle() { return m_hasCycle; }
};


void Cycle::dfs(Graph& G, int now, int pre)
{
	m_visited->at(now) = 1;
	for (auto next : G.adj(now) ) {
		
		if (!m_visited->at(next)) {
			dfs(G, next, now);
		}
		else if (next != pre) {
			m_hasCycle = true;
		}
	}
}

Cycle::Cycle(Graph& G)
{
	int n = G.V();
	m_visited = new vector<int>(n, 0);
	for (int i = 0; i < n; i++) {
		if (!m_visited->at(i)) {
			dfs(G, i, i);
		}
	}
}

void testCycle()
{
	Graph G("data.txt");
	Cycle cle(G);
	printf_s("has cycle ? "), cout<<(cle.hasCycle())<<endl;
}

二分图问题

用两种颜色上色,并且保证相同颜色的节点不相邻,能这样上色的就是二分图。例如,演员和电影的关系图,电影电影之间要通过演员连接。

方法:用dfs搜索,保证【now,next】颜色不同。当出现【now】和【next】都已经标记,且同色,涂色失败,即不可能是二分图。

TwoColor.h

#pragma once
#include"Graph.h"
class TwoColor
{
private:
	vector<bool>* m_visited = nullptr;
	vector<bool>* m_color = nullptr;
	bool m_isTwoColorable = true;

	void dfs(Graph& G, int v);
public:
	TwoColor() {}
	TwoColor(Graph& G);

	bool isBipartite() {
		return m_isTwoColorable;
	}
};

void TwoColor::dfs(Graph& G, int v)
{
	m_visited->at(v) = true;

	for (auto& next : G.adj(v)) {
		if (!m_visited->at(next)) {
			m_color->at(next) = !m_color->at(v);
			dfs(G, next);
		}//孩子已经标记且和父亲同色
		else if (m_color->at(next) == m_color->at(v)) {
			m_isTwoColorable = false;
		}
	}

}

TwoColor::TwoColor(Graph& G)
{
	m_visited = new vector<bool>(G.V(), false);
	m_color = new vector<bool>(G.V(), false);

	for (int i = 0; i < G.V(); ++i) {
	//遍历所有节点去涂色
		if (!m_visited->at(i)) {
			dfs(G, i);
		}
	}
}

//测试当前的类
void testTwoColor()
{
	Graph G("data.txt");
	TwoColor two(G);
	cout << (two.isBipartite()) << endl;

}

data.txt

6
6
1 3
3 5
1 4
4 5
2 4
0 5
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值