拓扑排序

思路,只需要一直把没有限制的事件做了就好了

1.开一个队列,循环一遍把度为0 的点都放进去
2.队列中取一个出来,把他记录下来,然后把有他限制的点度数减一,如果这个点的度为0,就放进队列
3.一直重复2,直到队列为空
3最后如果记录的答案小于总点数,那么存在环,否则有答案

如果要按字典序输出,把队列改成优先队列就好了

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#define sf scanf
#define scf(x) scanf("%d",&x)
#define scff(x,y) scanf("%d%d",&x,&y)
#define scfff(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define vi vector<int>
#define mp make_pair
#define pb push_back
#define pf printf
#define prf(x) printf("%d\n",x)
#define mm(x,b) memset((x),(b),sizeof(x))
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=a;i>=n;i--)
typedef long long ll;
using namespace std;
const ll mod=1e9+7;
const double eps=1e-6;
const double pi=acos(-1.0);
const int inf=0xfffffff;
const int N=1e5+7;
vector<int> ans;	//直接用ector储存就行 
struct Edge
{
	int to,next;
}edge[N*5];
int indegree[N];
int node[N],cnt;
void add_edge(int x,int y)
{
	edge[cnt].next =node[x];
	edge[cnt].to =y;
	node[x]=cnt++;
	indegree[y]++;
}
queue<int>v;	//不要求字典序 
//priority_queue<int, vector<int>, greater<int> > v;要求字典序用优先队列 
void init()
{
	mm(node,-1);
	mm(indegree,0);
	cnt=0;
}
void solve(int n)
{
	rep(i,1,n+1)
		if(indegree[i]==0)
		{
			v.push(i);	 
			ans.push_back(i);
		}
	while(!v.empty())
	{
		int x=v.front() ;v.pop();
		for(int i=x;i!=-1;i=edge[i].next)	//不要求字典序 
		{
			int to=edge[i].to;
			indegree[to]--;
			if(indegree[to]==0)
			{
				v.push(to);
				ans.push_back(to);
			}
		}
	}
}
void display(int n)	//	输出
{
	if(ans.size()!=n)
		pf("NO ANSWER\n");	//不是vag图,无解
	else
	{
		rep(i,0,ans.size())
		{
			if(i==ans.size()-1) pf("%d\n",ans[i]);
			else pf("%d ",ans[i]);
		}
	}
} 
int main()
{
	int n,m,x,y;scff(n,m);
	init();
	while(m--)
	{
		scff(x,y);	 
		add_edge(x,y);	//想要完成y,必须先完成x; 
	}
	solve(n);
	display(n);
	return 0;
}
posted @ 2018-12-07 22:17  一无所知小白龙  阅读(129)  评论(0编辑  收藏  举报