Description:
题目大意:John 有 n 个任务要做。任务不是独立的,一个任务只能另一个任务完成情况下执行。有 n 个任务,m 个 任务关系,求完成任务的顺序。
解题思路:
算法标签:拓扑排序
创建一个队列维护入度为0的节点集合,显然入度为0意味着目前已经没有需要在它之前完成的任务,所以打印该节点。每次打印的节点,与它邻接的节点入度减一,因为需要在它之前完成的任务已经完成了。最后注意末尾空格。
代码:
// TSWorld
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <stack>
#include <list>
using namespace std;
#define rep(i,l,r) for(int i = l; i <= r;i++)
#define ll long long
const int N = 1005;
class Graph
{
int v;
// 邻接表
list<int>* adj;
// 维护一个入度为0的顶点集合
queue<int>q;
// 入度
int* indegree;
public:
Graph(int v);
~Graph();
// Add Edge
void addEdge(int v,int u);
// Topological Sort
void TopologicalSort();
};
Graph::Graph(int v) {
this->v = v;
adj = new list<int>[v+5];
indegree = new int[v+5];
// 入度初始化为0
for(int i = 1;i <= v;i++)
indegree[i] = 0;
}
Graph::~Graph() {
delete[] adj;
delete[] indegree;
}
void Graph::addEdge(int v,int u) {
adj[v].push_back(u);
indegree[u]++;
}
void Graph::TopologicalSort() {
list<int>::iterator iter;
// 将入度为0的节点添加到队列
for(int i = 1;i <= v;i++)
if(indegree[i] == 0)
q.push(i);
int cnt = 0;
while(!q.empty()) {
int head = q.front();
q.pop();
// 消除末尾空格
if(cnt++ != 0)
cout<<" ";
cout<<head;
for(iter = adj[head].begin();iter != adj[head].end();iter++)
if(!(--indegree[*iter]))
q.push(*iter);
}
cout<<endl;
}
int main()
{
int n = 0,m = 0,u = 0,v = 0;
while(cin>>n>>m) {
if(n == 0 && m == 0)
break;
Graph graph(n);
for(int i = 1;i <= m;i++) {
scanf("%d%d",&v,&u);
graph.addEdge(v,u);
}
graph.TopologicalSort();
}
return 0;
}