一开始打算使用输出入度为0的点,然后删除点和这个点出边,直到输出所有点。但是复杂度很高。
一开始也很多WA,后来发现是m值可以为0,代表没有条件,所以随便排序。如果采用m&&n的话,m=0的条件就
会WA。
后来才发现,这个思想大概是用Khan法排序,维护一个入度为0的容器。
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
const int maxn=100+10;
int tu[maxn][maxn];
int n,m;
bool judge(int t){
for(int i=1;i<=n;i++){
if(tu[i][t]){
return false;
}
}
return true;
}
void clr(int t){
for(int i=1;i<=n;i++){
tu[t][i]=0;
}
}
int main(void){
// FILE *f=fopen("C:\\Users\\wrnge\\Desktop\\ACM\\UVA-10305.txt","w");
while(scanf("%d %d",&n,&m)==2&&m&&n){
// if(n==1){
// printf("1\n");
// continue;
// }
//初始化
memset(tu,0,sizeof(tu));
int exist[maxn];
for(int i=1;i<=n;i++){
exist[i]=1;
}
//Read
for(int i=0;i<m;i++){
int a,b;
scanf("%d %d",&a,&b);
tu[a][b]=1;
}
//special
if(n==1){
printf("1\n");
continue;
}
//process
int ct=n;
while(ct){
for(int i=1;i<=n;i++){
if(exist[i])
if(judge(i)){//删除节点和删除这个节点的出边
printf("%d",i);
ct--;
printf(ct?" ":"\n");
clr(i);
exist[i]=0;
}
}
}
}
// fclose(f);
}
后面的思想是采用dfs,这样是维护一个出度为0的容器。dfs让后面的节点先入栈。
// DFS
#include<iostream>
#include<string.h>
#include<cstdio>
using namespace std;
const int maxn = 1000 + 5;
int a[maxn][maxn];
int c[maxn];
int topo[maxn];
int n, m, t;
bool dfs(int u){
c[u] = -1;//访问一个节点,
for(int v=1; v<=n; v++){
if(a[u][v]){//如果有u指向v的边
if(c[v] < 0) return false;//如果v正在被访问,则有环,错误
else if(!c[v] && !dfs(v)) return false;//如果v未访问过,那么就继续访问v
}
}
c[u] = 1;
topo[--t] = u;//DFS表示,是在后面的节点都已经排好顺序之后,再插入U节点
return true;
}
bool topo_sort(){
t = n;
memset(c, 0, sizeof(c));
for(int u=1; u<=n; u++){
if(!c[u]){
if(!dfs(u)) return false;
}
}
return true;
}
int main(){
int j, k;
while(scanf("%d %d", &n, &m) == 2 && (n || m )){
memset(a, 0, sizeof(a));
for(int i=0; i<m; i++){
cin >> j >> k;
a[j][k] = 1;
}
if(topo_sort()){
for(int i=0; i<n; i++){
if(i == 0) cout << topo[i];
else cout << " " << topo[i];
}
cout << endl;
}
else
cout << "No" << endl;
}
return 0;
}