Vijos P1985【拓扑】被遗忘的时光

Description

  Lost-Monkey赢了精灵,精灵告诉Lost-Monkey,神庙里被恶魔封印了一个名为Lostangle的天使,如果想把它释放出来,需要将n个时间点排序,而精灵只知道m条形如a在b前的信息。
  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

Sample Output

1 2 3

Hint

数据范围约定:
  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;
}
阅读更多 登录后自动展开
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页