拓扑排序
思路,只需要一直把没有限制的事件做了就好了
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;
}