题目描述:
题目来源: POJ2367:http://poj.org/problem?id=2367
题目大意:
求1到n的其中一种拓扑序,保证存在一种拓扑序。输入格式是:第一行读入n,接下来n行,第i+1行表示有由i指向其他点的边,以0结尾。(直接一个0就是它没有连向任何点)。
样例输入:
5
0
4 5 1 0
1 0
5 3 0
3 0
样例输出:
2 4 5 3 1
题目分析:
一道拓扑排序模板题,而且题目保证是有解的,就不用判有没有环什么的,直接求就行。
不会拓扑序的请看我的讲解:http://blog.youkuaiyun.com/qianguch/article/details/77411160
附代码:
方法1:寻找入度为0的点
#include<iostream>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<ctime>
#include<iomanip>
#include<cctype>
#include<algorithm>
using namespace std;
const int maxn=110;
int n,du[maxn],to[maxn*maxn],nxt[maxn*maxn],first[maxn],tot,y;
queue<int>q;
void create(int u,int v)
{
tot++;
nxt[tot]=first[u];
first[u]=tot;
to[tot]=v;
}
void find()
{
while(!q.empty())
{
int u=q.front();
q.pop();
printf("%d ",u);
for(int e=first[u];e;e=nxt[e])
{
du[to[e]]--;
if(du[to[e]]==0) q.push(to[e]);
}
}
}
int main()
{
//freopen("lx.in","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;i++)
while(scanf("%d",&y),y!=0)
{
create(i,y);
du[y]++;
}
for(int i=1;i<=n;i++)
if(du[i]==0)
q.push(i);
find();
return 0;
}
方法2:dfs
#include<iostream>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<ctime>
#include<iomanip>
#include<cctype>
#include<algorithm>
using namespace std;
const int maxn=110;
int n,ans[maxn],to[maxn*maxn],nxt[maxn*maxn],first[maxn],tot,y,num;
bool vis[maxn];
void create(int u,int v)
{
tot++;
nxt[tot]=first[u];
first[u]=tot;
to[tot]=v;
}
void dfs(int u)
{
for(int e=first[u];e;e=nxt[e])
if(vis[to[e]]==false)
{
vis[to[e]]=true;
dfs(to[e]);
}
ans[++num]=u;
}
int main()
{
//freopen("lx.in","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;i++)
while(scanf("%d",&y),y!=0)
create(i,y);
for(int i=1;i<=n;i++)
if(vis[i]==false)
{
vis[i]=true;
dfs(i);
}
for(int i=num;i>=1;i--)
printf("%d ",ans[i]);
return 0;
}