题意:
假设有n个变量,还有m个二元组(u,v),分别表示变量u小于v。那么,所有变量从小到大排列起来应该是什么样子呢?例如,有4个变量a,b,c,d,若已知a<b,c<b,d<c
,则这4个变量的排序可能是a<d<c<b
。尽管还有其他可能(如d<a<c<b
)你只需找出其中一个即可。
题解:
把每个变量看成一个点,”小于”关系看成有向边,则得到一个有向图。这样,我们的任务实际上是把一个图的所有结点排序,使得每一条有向边(u,v)对应的u都排在v的前面。在图论中,这个问题成为拓扑排序。
不难发现:如果图中存在有向环,则不存在拓扑排序,反之则存在。不包含有向环的有向图称为有向无环图。
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1010;
int c[maxn];
int topo[maxn],t,n;
int G[maxn][maxn];
bool dfs(int u)
{
c[u]=-1;
for(int v=1;v<=n;v++)
if(G[u][v])
{
if(c[v]<0) return false;
else if(!c[v]&&!dfs(v)) return false;
}
c[u]=1;
topo[--t]=u;
return true;
}
bool toposort()
{
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 m;
while(cin>>n>>m&&n+m)
{
memset(G,0,sizeof(G));
int u,v,i;
for(i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
G[u][v]=1;
}
if(toposort())
{
for(i=0;i<n-1;i++)
{
printf("%d ",topo[i]);
}
printf("%d\n",topo[n-1]);
}
}
return 0;
}