例题 6-15 UVa10305-Ordering Tasks(拓扑序列)

第一次接触到的拓扑序列的题。尝试了邻接表和邻接矩阵+深搜两种写法,后者是紫书的方法。邻接表的方法是考察每个点的入度,邻接矩阵的方法是通过深搜找到每条路径的终点,将它比喻为结果的话,它的父结点就是它的依附条件,同理推下去,每次深搜得到的点都应该放在当前拓扑序列的队首。

题目链接:UVa 10305

AC代码:

邻接表解法:

#include 
#include 
#include 
using namespace std;

class Graph
{
	int v;
	list<int>* adj; //邻接表
	queue<int> q;  //维护一个入度为0的顶点集合
	int* indegree;
public:
	Graph(int v);
	~Graph();
	void addEdge(int v, int w);  //添加边
	void topo();  //拓扑排序
};

Graph::Graph(int v) {
	this->v = v;
	adj = new list<int>[v + 1];
	indegree = new int[v + 1];
	for (int i = 1; i <= v; i++)  //入度初始化为0
		indegree[i] = 0;
}
Graph::~Graph() {
	delete[] adj;
	delete[] indegree;
}
void Graph::addEdge(int v, int w) {  //v是起点,w是终点
	adj[v].push_back(w);
	++indegree[w];  //终点入度加一
}
void Graph::topo() {
	for (int i = 1; i <= v; i++)
		if (indegree[i] == 0)
			q.push(i);
	int cnt = 0;
	while (!q.empty()) {
		int a = q.front(); q.pop();
		if (cnt++ != 0)
			cout << " ";
		cout << a;
		for (auto& p : adj[a])
			if (!(--indegree[p]))
				q.push(p);
	}
	cout << endl;
}
int main() {
	int m, n, v, w;
	while (cin >> m >> n && m) {
		Graph G(m);
		while (n--) {
			cin >> v >> w;
			G.addEdge(v, w);
		}
		G.topo();
	}
	return 0;
}

邻接矩阵+DFS:

#include 
#include 
#include 
using namespace std;
const int maxn = 200;

bool G[maxn][maxn], visit[maxn];  //邻接矩阵和访问标志
int n, m;
list<int> topo;

void dfs(int task) {
	for (int i = 1; i <= n; i++) 
		if (!visit[i] && G[task][i]) {
			visit[i] = true;
			dfs(i);
			topo.push_front(i); //先存入“结果”,后存入“条件”
		}
}
int main() {
	int v, w;
	while (cin >> n >> m && n) {
		memset(G, false, sizeof(G));
		memset(visit, false, sizeof(visit));
		for (int i = 0; i < m; i++) {
			cin >> v >> w;
			G[v][w] = true;
		}
		for (int i = 1; i <= n; i++)
			if (!visit[i]) {
				visit[i] = true;
				dfs(i);
				topo.push_front(i);
			}
		cout << topo.front();
		topo.pop_front();
		while (!topo.empty()) {
			cout << " " << topo.front();
			topo.pop_front();
		}
		cout << endl;
	}
	return 0;
}

你可能感兴趣的:(第6章,数据结构基础)