1. 程式人生 > >p1242 字典序最小的拓撲序

p1242 字典序最小的拓撲序

題目

描述 Description
給定一個有N個節點的有向圖(編號為0~N-1),求其拓撲排序的最小字典序。
輸入格式 Input Format
第一行兩個整數 N和M,表示圖有N個點,M條邊。
接下來M行,2個整數ui和vi,表示ui到vi有條有向邊。
輸出格式 Output Format
N個用空格隔開的整數,表示拓撲序列。
樣例輸入 Sample Input

3 2
0 2
1 2
樣例輸出 Sample Output

0 1 2
時間限制 Time Limitation
1s
註釋 Hint
對於60%的資料,N ≤ 1, 000。
對於100%的資料,N ≤ 100, 000,M ≤ 1, 000, 000。

程式碼

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
	ll f=1,num=0;
	char ch=getchar();
	while (ch<'0'||ch>'9') { if (ch=='-') f=-1;ch=getchar(); }
	while (ch>='0'&&ch<='9') num=(num<<1)+(num<<3)+ch-'0',ch=getchar();
	return num*
f; } ll n,m,tot; ll ver[1000010],Next[1000010],head[100010],ans[100010],v[100010]; void add(int x,int y) { ver[++tot]=y,Next[tot]=head[x],head[x]=tot; } void topsort() { priority_queue<int,vector<int>,greater<int> >q; for (int i=0;i<n;i++) if (!v[i]) q.push(i); while (!q.empty()) { int x=q.top(
); q.pop(); ans[++tot]=x; for (int i=head[x];i;i=Next[i]) { int y=ver[i]; --v[y]; if (!v[y]) q.push(y); } } } int main() { n=read(),m=read(); for (int i=1;i<=m;i++) { ll x=read(),y=read(); add(x,y); ++v[y]; } tot=0; topsort(); for (int i=1;i<=n;i++) cout<<ans[i]<<' '; return 0; }