#include <cstdio> #include <vector> #include <queue> #include <algorithm> using namespace std; const int MAXN = 505; vector<int> Graph[MAXN]; int TopNum[MAXN], NodeNum[MAXN];; int NumVertex, NumEdge; // 有向无环图一定存在拓扑序 void TopoSort() { // 维护入度为0的节点,编号从小到大排序,保证编号小的节点的拓扑序小 priority_queue<int, vector<int>, greater<int> > que; // 将入度为0的节点加入队列 for(int i=1; i<=NumVertex; ++i) { if(Graph[i][0] == 0) que.push(i); } // 循环处理入度为0的节点,并赋予拓扑序 int cnt = 0; while(!que.empty()) { int u = que.top(); que.pop(); // 将最较小拓扑序号赋给入度为0且当前编号最小的节点 TopNum[u] = ++cnt; // 删除节点u出发的边,并调整其它节点的入度 for(int i=1; i<Graph[u].size(); ++i) { // 将调整后入度为0的节点加入队列 if(--Graph[Graph[u][i]][0] == 0) que.push(Graph[u][i]); } } // 图中存在环则无拓扑序 if(cnt != NumVertex) return; // 如果图并不一定是全联通的,那么判原图的某一连通域中是否存在环: for(int i=1; i<=NumVertex; ++i) if(Graph[i][0]) puts("somerwhere of the graph has a cycle"); // 输出以拓扑序排列的节点编号 for(int i=1; i<=NumVertex; ++i) NodeNum[TopNum[i]] = i; for(int i=1; i<=NumVertex; ++i) printf("%d%c", NodeNum[i], i==NumVertex?‘\n‘:‘ ‘); } int main() {//freopen("sample.txt", "r", stdin); while(~scanf("%d%d", &NumVertex, &NumEdge)) { // 初始化 for(int i=1; i<=NumVertex; ++i) { Graph[i].clear(); // 初始化入度 Graph[i].push_back(0); } // 建图 for(int i=1; i<=NumEdge; ++i) { int u, v; scanf("%d%d", &u, &v); // 使用邻接表时,重边对于拓扑序无影响,所以可以不用处理 //if(find(Graph[u].begin(), Graph[u].end(), v) // == Graph[u].end()) { Graph[u].push_back(v); // v节点的入度加1 ++Graph[v][0]; } } // 拓扑排序 TopoSort(); } return 0; }