E. Minimal Labels
time limit per test
1 secondmemory limit per test
256 megabytesinput
standard inputoutput
standard outputYou are given a directed acyclic graph with n vertices and m edges. There are no self-loops or multiple edges between any pair of vertices. Graph can be disconnected.
You should assign labels to all vertices in such a way that:
- Labels form a valid permutation of length n — an integer sequence such that each integer from 1 to n appears exactly once in it.
- If there exists an edge from vertex v to vertex u then labelv should be smaller than labelu.
- Permutation should be lexicographically smallest among all suitable.
Find such sequence of labels to satisfy all the conditions.
Input
The first line contains two integer numbers n, m (2 ≤ n ≤ 105, 1 ≤ m ≤ 105).
Next m lines contain two integer numbers v and u (1 ≤ v, u ≤ n, v ≠ u) — edges of the graph. Edges are directed, graph doesn't contain loops or multiple edges.
Output
Print n numbers — lexicographically smallest correct permutation of labels of vertices.
Examples
input
3 3
1 2
1 3
3 2
output
1 3 2
input
4 5
3 1
4 1
2 3
3 4
2 4
output
4 1 2 3
input
5 4
3 1
2 1
2 3
4 5
output
3 1 2 4 5
我一开始是用的正向拓扑,从入度为0的点开始,然后每次选择序号最小的那个,然后很快就发现错误了,
然后我就想到了记录一下每个点的最小前序节点,这样便可以使最小前序节点最小,然后还是wa了,因为如果出现两个点的最小前序节点相同那么,就必须要考虑次小前序节点的,这样下去再也没想到好的思路。
看了题解的反向拓扑,始终没有看懂是如何证明的,结合我的笨方法,才有点思路。
如果最小前序节点相同,那么肯定是有一个公共节点,次小前序节点必定是在这两个点到公共节点的路上,那么去掉这个公共节点,
考虑最前端的两个点,如果较小的那个点是这两条路的最小前序节点的话那么先选择较大的那个点并去掉,在考虑最前端的两个点,这样可以保证最小前序节点最小,如此下去便是正解。
#include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> #include<iostream> #include<queue> #include<map> #include<cmath> #include<set> #include<stack> #define ll long long #define pb push_back #define max(x,y) ((x)>(y)?(x):(y)) #define min(x,y) ((x)>(y)?(y):(x)) #define cls(name,x) memset(name,x,sizeof(name)) #define pos first #define index second #define mp make_pair using namespace std; const int inf=1e9+10; const ll llinf=1e16+10; const int maxn=1e5+10; const int maxm=2e5+10; const int mod=1e9+7; int n,m; int ans[maxn]; int outc[maxn]; vector<int> v[maxn]; void solve() { int k=n; priority_queue<int> Q; for(int i=1;i<=n;i++) { if(outc[i]==0) Q.push(i); } int x; while(!Q.empty()) { x=Q.top(); Q.pop(); ans[x]=k--; for(int i=0;i<v[x].size();i++) { outc[v[x][i]]--; if(outc[v[x][i]]==0) Q.push(v[x][i]); } } } int main() { //freopen("in.txt","r",stdin); while(~scanf("%d %d",&n,&m)) { cls(outc,0); for(int i=1;i<=m;i++) { int a,b; scanf("%d %d",&a,&b); outc[a]++; v[b].pb(a); } solve(); for(int i=1;i<=n;i++) printf("%d%s",ans[i],i==n?" ":" "); } return 0; }