现在的位置: 首页 > 综合 > 正文

图的相关算法

2018年02月23日 ⁄ 综合 ⁄ 共 2583字 ⁄ 字号 评论关闭

图的基础相关算法有BFS,DFS,拓扑排序, 强连通分支,kruskal,prim,Bellman-Ford,Dijkstra。这些算法思想不难,就是代码容易忘记,所以将代码写在这里,以备复习。本文的代码都用邻接表结构。

图的邻接表结构定义:

struct Edge
{
	int id;
	Edge* pNext;
};

struct Vertex
{
	int id;
	Edge* pAdj;
};

struct ALGraph
{
	vector<Vertex> vec;
};

BFS:

void BFS(const ALGraph& g, int k)
{
	int size = g.vec.size();
	vector<int> visit(size, 0);
	queue<int> que;
	que.push(k);
	while (!que.empty())
	{
		int i = que.front();
		que.pop();
		visit[i] = 1;
		Edge* p = g.vec[i].pAdj;
		while (p != NULL)
		{
			if (visit[p->id] == 0)
			{
				visit[p->id] = 1;
				que.push(p->id);
			}
			p = p->pNext;
		}
	}
}

DFS:

void DFS_TR(const ALGraph& g, int k, vector<int>& s, vector<int>& f, int& time, vector<int>& visit)
{
	visit[k] = 1;
	s[k] = ++time;
	Edge* p = g.vec[k].pAdj;
	while (p != NULL)
	{
		if (visit[p->id] == 0)
			DFS_TR(g, p->id, s, f, time, visit);
		p = p->pNext;
	}
	f[k] = ++time;
}

void DFS(const ALGraph& g)
{
	int size = g.vec.size();
	vector<int> visit(size, 0);
	vector<int> s(size, 0);
	vector<int> f(size, 0);
	int time = 0;
	for (int i = 0; i < size; ++i)
	{
		if (visit[i] == 0)
			DFS_TR(g, i, s, f, time, visit);
	}
}

拓扑排序:借助DFS,将f[]按照逆序输出即可

void DFS_TR(const ALGraph& g, int k, vector<int>& s, vector<int>& f,
			int& time, vector<int>& visit, stack<int> stk)
{
	visit[k] = 1;
	s[k] = ++time;
	Edge* p = g.vec[k].pAdj;
	while (p != NULL)
	{
		if (visit[p->id] == 0)
			DFS_TR(g, p->id, s, f, time, visit, stk);
		p = p->pNext;
	}
	f[k] = ++time;
	//先访问完的节点先入栈
	stk.push(k);
}

void DFS(const ALGraph& g, stack<int>& stk)
{
	int size = g.vec.size();
	vector<int> visit(size, 0);
	vector<int> s(size, 0);
	vector<int> f(size, 0);
	int time = 0;
	for (int i = 0; i < size; ++i)
	{
		if (visit[i] == 0)
			DFS_TR(g, i, s, f, time, visit, stk);
	}
}

void Topo(const ALGraph& g)
{
	stack<int> stk;
	DFS(g, stk);
	while (!stk.empty())
	{
		cout << stk.top() << endl;
		stk.pop();
	}
}

SCC:强连通分支,运用两次DFS

void DFS_TR_G(const ALGraph& g, int k, vector<int>& s, vector<int>& f,
			int& time, vector<int>& visit, stack<int> stk)
{
	visit[k] = 1;
	s[k] = ++time;
	Edge* p = g.vec[k].pAdj;
	while (p != NULL)
	{
		if (visit[p->id] == 0)
			DFS_TR(g, p->id, s, f, time, visit, stk);
		p = p->pNext;
	}
	f[k] = ++time;
	//先访问完的节点先入栈
	stk.push(k);
}

void DFS_G(const ALGraph& g, stack<int>& stk)
{
	int size = g.vec.size();
	vector<int> visit(size, 0);
	vector<int> s(size, 0);
	vector<int> f(size, 0);
	int time = 0;
	for (int i = 0; i < size; ++i)
	{
		if (visit[i] == 0)
			DFS_TR_G(g, i, s, f, time, visit, stk);
	}
}


void DFS_TR_GT(const ALGraph& g, int k, vector<int>& s, vector<int>& f,
			int& time, vector<int>& visit)
{
	visit[k] = 1;
	s[k] = ++time;
	Edge* p = g.vec[k].pAdj;
	while (p != NULL)
	{
		if (visit[p->id] == 0)
			DFS_TR(g, p->id, s, f, time, visit, stk);
		p = p->pNext;
	}
	f[k] = ++time;
}

int DFS_GT(const ALGraph& g, stack<int>& stk)
{
	int size = g.vec.size();
	vector<int> visit(size, 0);
	vector<int> s(size, 0);
	vector<int> f(size, 0);
	int time = 0;
	int res = 0;
	while (!stk.empty())
	{
		int i = stk.top();
		stk.pop();
		if (visit[i] == 0)
		{
			++res;
			DFS_TR_GT(g, i, s, f, time, visit);
		}
	}
	return res;
}

void SCC(const ALGraph& g)
{
	stack<int> stk;
	DFS_G(g, stk);
	//计算g的转置图,这步很简单用伪代码,设gt为g的转置
	compute gt;
	int res = DFS_GT(gt, stk);	
}

抱歉!评论已关闭.