VJ链接(紫书P167)
简单的拓扑排序,但是自己对拓扑排序算不上熟练,用起来也是磕磕绊绊的,同时由于自己写的代码迟迟和样例输出一样,一直以为自己错了。后面才发现,这可是拓扑排序呀,我怎么这么笨,答案不唯一的。
题目大意:给n个任务,m个关系,输入m行(u, v),代表u < v。对n个任务进行从小到大的排序。
思路
vis[i][j]
表示 i < j 的关系,a[i]
表示比 i 小的元素的个数- 拓扑排序,如果
a[i] == 0
,就输出 i ,改变a[i]
的值,并且找出所有 i < j 的关系,使a[j]的值减一,同时把vis[i][j]进行标记
感悟
拓扑排序感觉用法比较固定,主要就是对元素之间的关系进行排序,题目通常会出现”答案不唯一“。需要注意的是,拓扑排序每次得到结果,都需要改变两个值(a和vis)。
代码如下
#include<iostream>
#include<cstring>
using namespace std;
int a[105],vis[105][105],b[105];
int n,m;
void topo(){
int num=0;
while(num<n){
for(int i=1;i<=n;i++){
if(!a[i]){
cout<<i;
a[i]=-1;
num++;
for(int j=1;j<=n;j++){
if(j!=i && vis[i][j]){
a[j]--;
vis[i][j]=0;
}
}
if(num!=n)cout<<" ";
else cout<<endl;
}
}
}
}
int main()
{
while(cin>>n>>m){
if(n==0&&m==0)break;
memset(a,0,sizeof(a));
memset(vis,0,sizeof(vis));
for(int i=0;i<m;i++){
int u,v;
cin>>u>>v;
if(vis[u][v]==0){
vis[u][v]=1;
a[v]++;
}
}
topo();
}
return 0;
}