此题主要运用拓扑排序
- 首先读取数据,存入一个图中,同时记录每个节点的入度;
- 然后再将入度为0的节点加入都优先队列中;
- 取优先队列的队首元素,并将此元素存到数组result中,然后依次遍历此节点的邻接点,同时将邻接点的入度减1,并将邻接点中入度为0的加入到优先队列中;
- 重复步骤三,直到队列为空;
#include <bits/stdc++.h>
using namespace std;
const int maxn = 10000 + 5;
vector<int> g[maxn]; //二维
int du[maxn]; //度
int n, m, L[maxn];
bool toposort() { //拓扑排序
memset(du, 0, sizeof(du));
for (int i = 0; i < n; i++){
for (int j = 0; j < g[i].size(); j++){
du[g[i][j]]++; //各点的度
}
}
int tot = 0;
priority_queue<int> Q;
for (int i = 0; i < n; i++)
if (!du[i])
Q.push(i); //入度为0的点存入优先队列
while (!Q.empty()) {
int x = Q.top();
Q.pop();
L[tot++] = x;//取出入度为0的点,并存入数组
for (int j = 0; j < g[x].size(); j++) { //把与取出的点相邻的点的入度减1
int t = g[x][j]; //相邻的点
du[t]--;
if (!du[t])
Q.push(t);//把入度为0的点放入优先队列
}
}
return tot == n;
}
int main() {
int T;
cin>>T;
while (T--) {
cin>>n>>m;
for (int i = 0; i < n; i++)
g[i].clear();
while (m--) {
int a,b;
cin>>a>>b;
g[a - 1].push_back(b - 1); //输入数据
}
int first = 0;
if (toposort()) {
for (int i = 0; i < n; i++) {
if (first)
cout<<" ";
first = 1;
cout<<(L[i]+1);
}
cout<<endl;
} else
cout<<"-1"<<endl;
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int G[1005][1005];//邻接矩阵
bool vis[1005];//标记点是否走过
int n,m;
bool isStart(int k){
for(int i=0;i<=n;i++){
if(G[i][k]) //判断这条边是否存在
return false;
}
return true;
}
bool hasHoop(){ //判断点是否走过
for(int i=1;i<=n;i++){
if(!vis[i])
return true;
}
return false;
}
void Do(){
priority_queue<int> pq; //优先队列
int loc=0;
int ans[1005];
for(int i=1;i<=n;i++){
if(isStart(i)){
pq.push(i); //先将入度为0的点填入优先队列
}
}
while (!pq.empty()){ //队列不空则一直循环
int k=pq.top();
pq.pop();
if(vis[k]){
continue;
}
ans[loc++]=k; //最后输出数组
vis[k]= true;
for(int i=1;i<=n;i++){
G[k][i]=0;
if(isStart(i)){
pq.push(i);
}
}
}
if(hasHoop()){
cout<<"-1"<<endl;
}else{
for(int i=0;i<n;i++){
if(i){
cout<<" ";
}
cout<<ans[i];
}
cout<<endl;
}
}
int main(){
int T;
cin>>T;
while (T--){
cin>>n>>m;
for(int i=0;i<m;i++){
int a,b;
cin>>a>>b;
G[a][b]=1;
}
Do();
}
return 0;
}
/*
1
4 3
1 2
2 3
4 3
4 1 2 3
*/