拓扑排序之一
//拓扑排序:若G包含有向边(U,V),则在序列中U出现在V之前,即该序列使得图中所有有向边均从左指向右。
//如果图是有回路的,就不存在这样的序列。
//首先选择一个无前驱的顶点(即入度为0的顶点,图中至少应该有一个这样的顶点,否则肯定存在回路),
//然后从图中移去该顶点以及由其发出的所有有向边,如果图中还存在无前驱的顶点,则重复上述操作,直到操作无法进行。
//如果图不为空,说明图中存在回路,无法进行拓扑排序;否则移出的顶点的顺序就是对该图的一个拓扑排序。
//poj 2367 Genealogical tree
#include<iostream> //简单拓扑排序
using namespace std;
int n,side[102][102],in[102],path[102];
int main()
{
cin>>n;
int a,rear=0;
for(int id=1;id<=n;++id)
{
while(cin>>a&&a)
{
side[id][a]=1;
in[a]++;
}
}
for(int i=1;i<=n;++i)
if(in[i]==0)
path[rear++]=i;
for(int i=0;i<rear;++i)
{
for(int j=1;j<=n;++j)
if(side[path[i]][j]==1)
{
in[j]--;
if(in[j]==0)
path[rear++]=j;
}
}
for(int i=0;i<rear;++i)
cout<<path[i]<<" ";
cout<<endl;
return 0;
}
//poj 2367 Genealogical tree
#include<iostream> //算法竞赛入门经典 P111
using namespace std;
int G[102][102],c[102],topo[102];
int n,t;
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]&&!dfs(u))
return false;
return true;
}
int main()
{
memset(G,0,sizeof(G));
int i,j;
cin>>n;
for(i=1;i<=n;++i)
{
while(cin>>j&&j)
G[i][j]=1;
}
if(toposort())
{
for(int i=1;i<=n;++i)
printf("%d ",topo[i]);
printf("\n");
}
return 0;
}