描述
给定一个包含nn个点mm条边的有向无环图,求出该图的拓扑序。若图的拓扑序不唯一,输出任意合法的拓扑序即可。若该图不能拓扑排序,输出-1−1。
输入描述:
第一行输入两个整数n,mn,m ( 1\le n,m \le 2\cdot 10^51≤n,m≤2⋅105),表示点的个数和边的条数。
接下来的mm行,每行输入两个整数u_i,v_iui,vi (1\le u,v \le n1≤u,v≤n),表示u_iui到v_ivi之间有一条有向边。
接下来的mm行,每行输入两个整数u_i,v_iui,vi (1\le u,v \le n1≤u,v≤n),表示u_iui到v_ivi之间有一条有向边。
输出描述:
若图存在拓扑序,输出一行nn个整数,表示拓扑序。否则输出-1−1。
示例1
输入:
5 4 1 2 2 3 3 4 4 5复制
输出:
1 2 3 4 5
该题目和检测循环依赖类似,但检测循环依赖的数量级小,使用图的遍历可以解决,本题数量级大,使用图的遍历会超时。
看题解使用每个节点“入度”统计来解决
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
//使用检测循环依赖相同的解法会超时
/*vector<int>path;
vector<int>res;
vector<int>visit;
bool flag = false;
void bfs(vector<vector<int>>&dp, int t) {
if (find(path.begin(), path.end(), t) != path.end()) {
flag = true; //有环
return;
}
if (visit[t]) {
return;
}
visit[t] = 1;
path.push_back(t);
for (int i = 0; i < dp[t].size(); i++) {
if (flag) break;
bfs(dp, dp[t][i]);
}
path.pop_back();
res.push_back(t);
}
int main() {
int n, m;
while (cin >> n >> m) { // 注意 while 处理多个 case
vector<vector<int>>dp(n+1, vector<int>());
path.resize(n);
res.resize(n);
visit.resize(n, 0);
for (int i = 0; i < m; i++)
{
int tmp1, tmp2;
cin >> tmp1;
cin >> tmp2;
dp[tmp1].push_back(tmp2);
}
for (int i = 0; i < n; i++) {
if (flag) break;
bfs(dp, i+1);
}
if (flag) {
cout << -1 << endl;
break;
}
reverse(res.begin(), res.end());
cout << res[0];
for (int i = 1; i < res.size(); i++) {
if (res[i] != 0) {
cout << " " << res[i];
}
}
cout << endl;
}
return 0;
}*/
int main() {
int n, m;
while (cin >> n >> m) { // 注意 while 处理多个 case
vector<vector<int>>dp(n+1, vector<int>());
vector<int>inDegree(n+1);
queue<int> que;
vector<int>res;
int cnt = 0;
for (int i = 0; i < m; i++)
{
int tmp1, tmp2;
cin >> tmp1;
cin >> tmp2;
dp[tmp1].push_back(tmp2);
inDegree[tmp2]++;
}
for (int i = 1; i <= n; i++) {
if (inDegree[i] == 0) {
que.push(i);
}
}
while (!que.empty()) {
int u = que.front();
res.push_back(u);
que.pop();
for (int i = 0; i < dp[u].size(); i++) {
inDegree[dp[u][i]]--;
if (inDegree[dp[u][i]] == 0) {
que.push(dp[u][i]);
}
}
cnt++;
}
if (cnt != n) {
cout << -1 << endl;
continue;
}
cout << res[0];
for (int i = 1; i < res.size(); i++) {
cout << " " << res[i];
}
cout << endl;
}
return 0;
}
// 64 位输出请用 printf("%lld")

京公网安备 11010502036488号