Description
Lost-Monkey赢了精灵,精灵告诉Lost-Monkey,神庙里被恶魔封印了一个名为Lostangle的天使,如果想把它释放出来,需要将n个时间点排序,而精灵只知道m条形如a在b前的信息。
Lost-Monkey一听到有天使,很想见见天使到底长什么样,可惜时间点太多,他觉得这几乎是不可能的任务,好在身为在他旁边的XXX,你,传说中的impossible is nothing,一定知道如何解决啦!!
Lost-Monkey一听到有天使,很想见见天使到底长什么样,可惜时间点太多,他觉得这几乎是不可能的任务,好在身为在他旁边的XXX,你,传说中的impossible is nothing,一定知道如何解决啦!!
Input
第一行n,m;接下来m行,每行2个数a,b;意义均同上。
Output
输出文件仅一行,若可以将n个时间点排序,则输出字典序最小的一种方案,否则输出“NO SOLUTION”。
Sample Input
3 2
1 2
2 3
1 2
2 3
Sample Output
1 2 3
Hint
数据范围约定:
40%的数据,n<=1000,m<=1000
100%的数据,n<=100000,m<=500000
40%的数据,n<=1000,m<=1000
100%的数据,n<=100000,m<=500000
分析
很水的一个 前向星拓扑排序裸题QWQ。我也不知道这种题我要怎么描述,于是乎就来讲讲拓扑。(想看就看--->)寻找入度为0的点,删去后删掉与其相连的边,重复循环知道没有入度为0的点或者全部点都用完。邻接矩阵自动字典序,如果是前向星&邻接表的时候用小根堆或者STL的priority_queue(优先队列)。
//题解by disangan233 or Lixiuyu
#include<bits/stdc++.h>
using namespace std;
#define re register long long
#define ll long long
ll n,m,cnt,h[500005],rd[100005],ans[100005];
struct did{
ll to,next;
}e[500005];
priority_queue<int,vector<int>,greater<int> >q;
inline ll read()
{
char did=getchar();
re luoyang=0,yz=1;
while(!isdigit(did)){if(did=='-')yz=-1;did=getchar();}
while(isdigit(did))luoyang=luoyang*10+did-'0',did=getchar();
return yz*luoyang;
}
inline void add(ll x,ll y)
{
e[++cnt].to=y;
e[cnt].next=h[x];
h[x]=cnt;
}
inline ll tpsort()
{
for(re i=1;i<=n;i++)
if(!rd[i])
q.push(i);
for(re i=1;i<=n;i++)
{
if(q.empty())return 0;
re top=q.top();q.pop();
ans[++ans[0]]=top;
for(re j=h[top];j;j=e[j].next)
{
re to=e[j].to;
rd[to]--;
if(!rd[to])
q.push(to);
}
}
return 1;
}
int main()
{
n=read();m=read();
for(re i=1;i<=m;i++)
{
re a=read(),b=read();
add(a,b);rd[b]++;
}
if(tpsort())
for(re i=1;i<=n;i++)
cout<<ans[i]<<" ";
else cout<<"NO SOLUTION"<<endl;
return 0;
}